From: Hoehle, Joerg-C. <Joe...@t-...> - 2005-04-27 08:24:51
|
Hi, >> * Yaroslav Kavenchuk <xnirapuhx@wragl.ol> wrote: >> How define it? >> For example - printf. >see modules/bindings/glibc/linux.lisp and search for "fcntl". Excellent reference. Typically, you have a few polymorphic uses, like also for ioctl(). Typically, I wrote in the past that if the library that you want to interface to only contains/exports/documents something like printf() without providing vprintf(), then you should complain to the library provider. printf() is a convenience function for C programmers to allow them to call varargs functions easily when the number of arguments is known ni the source file. The real workhorse is vprintf(), i.e. the function that takes a pointer to an array. printf() is especially difficult to interface to since the argument types can all be different. When all are of the same kind, e.g. strings, here is what I wrote in modules/bindings/glibc/linux.lisp about the exec() family of functions: (def-call-out execv (:arguments (path c-string) (argv (c-array-ptr c-string))) (:return-type int) (:name "execv")) You see how clisp can very succintly describe the interface to execv() ; Foreign language interfaces should use the execv* series of functions, ; not the C varargs convenience functions. (defun execl (path &rest args) (execv path (coerce args 'vector))) Having printf() without vprintf() is akin to the same kind of stupidity (say limitation to be polite) when somebody only exports a macro interface without documenting the underlying function when all the macro does is to remove the need for quoting arguments at the interactive prompt. I hope nobody does so anymore these days in Common Lisp. What I mean is that to a C programmer, it's easier to wrote foo(a,b,c,...) than to construct an array and pass that. C provides ways to somehow work with that, so people use it this way. But they can only use it literally in C source files. They need something really different and quite complex when they want to do the equivalent of FUNCALL or APPLY, i.e. call that same function with an unknown number of arguments. Since you're interfacing to tcl libraries, I hope there's some function where you just pass an array of strings, or, like for fnctl(), a few different cases that you cover via a few different functions. Another possibility is to construct the function definition at run-time, using the FOREIGN-FUNCTION constructor and a list of memoized C-type declarations, based on the actual number of arguments. (apply (foreign-function #'the-0-or-1-arg-function ; get its address (memoized-parse-c-type `(c-function (:arguments ,(loop repeat (length args)) ...)))) args) Memoization is the key to acceptable performance. You should avoid PARSE-C-TYPE at run-time, it's a huge overhead. You could even try to memoize the function itself, but then need to check for valid (alive) function pointers in case you expect to be able to restart from a saved image file. That could be faster than the c-array-ptr solution when you have a list of arguments, especially if you cannot avoid to create a new vector for each call, since I expect (APPLY foreign-function my-args) to be as efficient as can be. Regards, Jorg Hohle |
From: Florian W. <fw...@de...> - 2005-04-27 09:22:38
|
* Joerg-Cyril Hoehle: > Hi, > >>> * Yaroslav Kavenchuk <xnirapuhx@wragl.ol> wrote: >>> How define it? >>> For example - printf. >>see modules/bindings/glibc/linux.lisp and search for "fcntl". > > Excellent reference. Does fcntl work on platforms where the number of non-variadic parameters influences the calling convention? (AMD64 could be one of them, there was a recent discussion on the GCC mailing list.) |