From: Sam S. <sd...@gn...> - 2003-07-31 23:47:43
|
1. why can't I pass NIL as a C-POINTER and have CLISP use NULL?! 2. <http://norsys.com/netica_c_api.htm> (def-c-type environ_ns_ c-pointer) (def-call-out new-netica-environ_ns (:arguments (license c-string) (env c-string) (locn c-string)) (:return-type environ_ns_) (:name "NewNeticaEnviron_ns")) (def-call-out init-netica_bn (:arguments (envp (c-ptr environ_ns_) :in-out) (mesg (c-ptr c-string) :out)) (:return-type int) (:name "InitNetica_bn")) for typedef struct environ__ns environ_ns; environ_ns* NewNeticaEnviron_ns (const char* license, environ_ns* env, const char* locn); int InitNetica_bn (environ_ns** envp, char* mesg); results in: [1]> (setq netica-env (netica:new-netica-environ_ns "foo" nil nil)) #<FOREIGN-ADDRESS #x100C7A70> [2]> (multiple-value-setq (status netica-env message) (netica:init-netica_bn netica-env)) Program received signal SIGSEGV, Segmentation fault. 0x0054aa24 in C_foreign_call_out (argcount=1, rest_args_pointer=0x14600d8) at fo reign.d:3294 3294 *resptr = convert_from_foreign(*resptr,results[i].address); (gdb) p results $1 = (result_descr (*)[0]) 0x6c206568 (gdb) p results[0] Cannot perform pointer math on incomplete types, try casting to a known type, or void *. (gdb) p results[i].address Cannot perform pointer math on incomplete types, try casting to a known type, or void *. (gdb) -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html> Growing Old is Inevitable; Growing Up is Optional. |
From: Hoehle, Joerg-C. <Joe...@t-...> - 2003-08-01 09:27:59
|
Hi, Here are some comments of mine on 1. NIL as parameter type 2. NIL and C-POINTER Sam wondered what he missed: ... The obvious from http://norsys.com/onLineAPIManual/index.html "mesg should be a pointer to a character array which is allocated at least MESG_LEN_ns characters long." (mesg (c-ptr (c-array character 12345-or-whatever)) :out) BTW, although it init* receives a pointer to pointer, I can see nowhere in the doc that env is an output type. Actually, it's left unclear what the old (in) and new (out) allowed or intended usage is (why a pointer to pointer at all?). Which pointer should Lisp use in the future: the old one from new-netica or the new one from init-netica? Or is this distinction just superfluous from a Lisp client point of view? I sent an e-mail to the netica people. BTW2, if you declared the second parameter to new_netica as c-string (which is not it's type, it's environ_ns) just so that you can easily supply NULL, other people have succesfully used NIL as a type declaration, even though impnotes says it's output only. I suggest removing that remark from impnotes and acknowledge observed practice instead. The code implements: # If we are presented the empty type, we take it as "ignore". Another implementation possibility would be not even to have to supply NIL as silly argument in the Lisp call, e.g. invoke (new-netica license locn) instead of (new-netica license anything-here-is-ignored locn). But that would break some current invariants about the number of arguments information that CLISP maintains and uses. It would also break existing code which uses that non-documented NIL-parameter-type feature. But I'd prefer it. >1. why can't I pass NIL as a C-POINTER and have CLISP use NULL?! It would be possible to add such polymorphism, but I'm not much in favour of such things unless the behaviour can be made symmetric. So the question becomes: what happens the other way round (e.g. as :return-type or as return from FOREIGN-VALUE)? 1b. What should be the value of conversion from C-POINTER when the foreign pointer happens to be NULL? Up to now, it is an object equalp to #<FOREIGN-ADDRESS 00000000>. A point to discuss is: is C-POINTER considered to return an *opaque* pointer, as impnotes say, or a not-so-opaque thing where NULL is recognized as a special case? IIRC, in my AFFI, I have both cases/types: :external -> FOREIGN-ADDRESS, always ("don't touch") * -> NULL->NIL special case, otherwise FOREIGN-* but having both cases has its root in history, not pragmatics. Changing the returned value to yield NIL for NULL has some pros: + It may lead to earlier detection of bugs. No code would attempt to dereference NIL (signal type error instead of dump core), or cast it to some other structure. + It would make detection of the NULL (bottom value) return easier (well, we have foreign-address-null (which, as a predicate, is missing a -p suffix)). + It would correspond to C pointer practice. and cons: - If it were changed to return NIL, it could break some code (where you expect to store a foreign-pointer object into a structure) -- I'm not sure. - problems arise when you don't know what the real nature of the abstract interface type is (e.g. they don't tell you whether it's an int or pointer or whatever). c-pointer would be useable only for pointers, but sometimes you really want an abtract foreign entity (00000000 by chance or not), and fixnum/bignum is not appropriate, because e.g. you can't FINALIZE that. For example (foreign-address-unsigned NIL) -> type error. I'm not sure at all whether it should not raise a type error and return 0 instead. There's a good reason that exceptional values are not mixed in with normal values in functional programming! FP makes union types always explicit, e.g. (OR fail xyz). Having all arguments/return-values implicitly as (OR xyz NULL) instead of just xyz makes for bugs in both C and Java. Ada can avoid this. CLISP can also (via C-PTR vs. C-PTR-NULL). Note that the special case you wish for already exists for C-FUNCTION and there in both directions. I.e. (typep {(:return-type (c-function...))} '(OR FUNCTION NULL)) is a tautology. Proposal: Let's change something! o Simultaneously accept NIL for c-pointer type and return NIL for c-pointer type. o Document that. o Leave foreign-address-unsigned as is. Their domain is FOREIGN-*, not (OR FOREIGN-* NULL). BTW, if you were to change, what should (unsigned-address-foreign 0) return? So let's keep it symmetric! o change foreign-address-null to accept NIL, despite its name. o Rename foreign-address-null to *-p suffix? o Or to foreign-null-p (since it also works on foreign-function objects and all foreign-* types)? Note that I also favour this return-maybe-NIL change in the light of possible FOREIGN-VARIABLE return types, should I ever implement that. Regards, Jorg Hohle. |
From: Sam S. <sd...@gn...> - 2003-08-01 15:18:22
|
> * In message <9F8582E37B2EE5498E76392AEDDCD3FE05C97186@G8PQD.blf01.telekom.de> > * On the subject of "FFI crash: what am I missing?!" > * Sent on Fri, 1 Aug 2003 11:27:17 +0200 > * Honorable "Hoehle, Joerg-Cyril" <Joe...@t-...> writes: > > Sam wondered what he missed: > ... The obvious from http://norsys.com/onLineAPIManual/index.html > "mesg should be a pointer to a character array > which is allocated at least MESG_LEN_ns characters long." > (mesg (c-ptr (c-array character 12345-or-whatever)) :out) Jorg, thank you very much!! > BTW2, if you declared the second parameter to new_netica as c-string > (which is not it's type, it's environ_ns) just so that you can easily > supply NULL, other people have succesfully used NIL as a type > declaration, even though impnotes says it's output only. but I won't be able to pass anything but NIL there, right? > >1. why can't I pass NIL as a C-POINTER and have CLISP use NULL?! > It would be possible to add such polymorphism, but I'm not much in > favour of such things unless the behaviour can be made symmetric. > > So the question becomes: what happens the other way round (e.g. as > :return-type or as return from FOREIGN-VALUE)? > > 1b. What should be the value of conversion from C-POINTER when the > foreign pointer happens to be NULL? Up to now, it is an object equalp > to #<FOREIGN-ADDRESS 00000000>. very interesting and enlightening discussion. what do other FFIs do here? CMUCL? ACL? LW? what behavior does UFFI expect? -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html> The difference between genius and stupidity is that genius has its limits. |
From: Sam S. <sd...@gn...> - 2003-08-01 22:37:44
|
> * In message <9F8582E37B2EE5498E76392AEDDCD3FE05C97186@G8PQD.blf01.telekom.de> > * On the subject of "FFI crash: what am I missing?!" > * Sent on Fri, 1 Aug 2003 11:27:17 +0200 > * Honorable "Hoehle, Joerg-Cyril" <Joe...@t-...> writes: > > > Sam wondered what he missed: > ... The obvious from http://norsys.com/onLineAPIManual/index.html > "mesg should be a pointer to a character array > which is allocated at least MESG_LEN_ns characters long." > (mesg (c-ptr (c-array character 12345-or-whatever)) :out) actually, c-array-max :-) now, the next trouble: <http://norsys.com/onLineAPIManual/functions/SetNodeProbs_bn.html> (def-call-out SetNodeProbs_bn (:arguments (node node_bn_) (parent_states (c-array-max state_bn #.MAX_PARENT)) (probs (c-array-max prob_bn #.MAX_STATE))) (:return-type nil)) I get a crash when I try to pass #() as the first argument cvs up ./configure --with-module=netica build-netica cd !$ gdb full run -B . -M full/lispinit.mem -i netica/demo ---please help!!!--- > >1. why can't I pass NIL as a C-POINTER and have CLISP use NULL?! > It would be possible to add such polymorphism, but I'm not much in > favour of such things unless the behaviour can be made symmetric. BTW, what about passing a NULL when C expects a variable length array? in the above, the doc says that I can pass NULL instead of the array of parents when there are no parents. what about making O(fp_zero) accessible in LISP so that the user will not have to resort to hacks like this: (let ((null nil)) (defun netica:null-pointer () "return a null foreign pointer" (unless (and null (ffi:validp null)) (setq null (ffi:unsigned-foreign-address 0))) null)) when a C function expects NULL, it is ugly to create a new NULL every time with (ffi:unsigned-foreign-address 0). using NIL is, of course, more elegant. So, what do other FFIs do here? -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html> Illiterate? Write today, for free help! |
From: Scott W. <or...@gm...> - 2003-07-31 23:58:39
|
Sam Steingold wrote: >1. why can't I pass NIL as a C-POINTER and have CLISP use NULL?! > >2. <http://norsys.com/netica_c_api.htm> > >(def-c-type environ_ns_ c-pointer) >(def-call-out new-netica-environ_ns > (:arguments (license c-string) (env c-string) (locn c-string)) > (:return-type environ_ns_) > (:name "NewNeticaEnviron_ns")) >(def-call-out init-netica_bn > (:arguments (envp (c-ptr environ_ns_) :in-out) (mesg (c-ptr c-string) :out)) > Did you mean "c-ptr-null"? |
From: Sam S. <sd...@gn...> - 2003-08-01 14:19:35
|
> * In message <3F2...@gm...> > * On the subject of "Re: FFI crash: what am I missing?!" > * Sent on Thu, 31 Jul 2003 17:54:03 -0600 > * Honorable Scott Williams <or...@gm...> writes: > > Sam Steingold wrote: > > >1. why can't I pass NIL as a C-POINTER and have CLISP use NULL?! > > > >2. <http://norsys.com/netica_c_api.htm> > > > >(def-c-type environ_ns_ c-pointer) > >(def-call-out new-netica-environ_ns > > (:arguments (license c-string) (env c-string) (locn c-string)) > > (:return-type environ_ns_) > > (:name "NewNeticaEnviron_ns")) > >(def-call-out init-netica_bn > > (:arguments (envp (c-ptr environ_ns_) :in-out) (mesg (c-ptr c-string) :out)) > > > Did you mean "c-ptr-null"? c-ptr-null is an incomplete type. -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html> He who laughs last did not get the joke. |