Open stergiotis opened 6 years ago
;; 1) declare memcpy with typed pointers to be able to use ftype-pointer (define memcpy/uptr (foreign-procedure "memcpy" (uptr uptr size_t) void)) ;; --> exception: invalid foreign-procedure argument type specifier uptr*
That's not how you say "pointer to an object of type uptr".
> (define memcpy/uptr* (foreign-procedure "memcpy" ((* uptr) (* uptr) size_t) void*))
> (memcpy/uptr* a b sz)
;; 3) make a void ftype-pointer (memcpy/void (make-ftype-pointer void b-addr) (make-ftype-pointer void a-addr))
- Seems to be quite nice as it allows to explicitly cast any pointer to void* which is a useful and proven idiom.
Your code and descriptive text don't match. You can make an ftype pointer to objects of void*
just fine, but that's not the same thing as an ftype pointer to the non-existent void
ftype.
It's true that Chez does not have any way to make an ftype pointer that points to an unknown ftype.
Thanks a lot for your quick response.
1) Is solved by using the proper syntax.
I am sorry for the confusion, the minimal example I gave above was perhaps a bit too minimalistic. The code I have been experimenting with established various ftype-name
s by means of the define-ftype
special form. These user-defined ftype-name
s do not seem to be available in the foreign-procedure
declaration: invalid (non-base) foreign-procedure argument ftype)
.
Regarding the void
pointer: You are right that constructing a void**
pointer is perfectly feasible in Chez (i.e. (make-ftype-pointer void* 0)
). It is also clear that the void*
case however is special as the void
type is not a proper datatype (e.g. (foreign-sizeof 'void)
is doomed). This however means proposition 2) would make sense as void*
pointers are not first-class citizens in Chez whereas they are in the interfaced language.
These user-defined ftype-names do not seem to be available in the foreign-procedure declaration: invalid (non-base) foreign-procedure argument ftype).
Foreign procedure definitions can use pointers to user-defined ftypes, but it cannot pass structs directly. There is a pull request currently under review ( #213 ) to enhance the foreign procedure system to allow passing and returning structs by value, but I don't know what the status of that review is.
I don't think that will help with your desire to have something closer to C's void*
type, though.
you just need a cffi for scheme like this https://github.com/evilbinary/scheme-lib/blob/master/apps/cffi-test.ss ,pretty eazy to call ffi.
Any update on this?
Pull request #213 has been merged. It describes how to pass structs directly.
The issue was not about passing structs using the C ABI . What I wanted to discuss originally were the following two limitations of the current ftype implementation:
1) Pointers to non-base types are currently not supported (e.g. (* (* char))
or (* my-ftype)
can not be used as argument types).
2) Pointers supplied for arguments declared as void*
do not get automatically cast when passed as function arguments.
In practice I found the ftype FFI system really nice to work with but I regularly need to work around these two limitations.
You can use (* ftype-name)
as a foreign-procedure argument type or return-value type for any user-defined ftype name as well as for any base ftype name. You're correct, however, that you can't use (* (* char))
, because the syntax requires _x_
in (* _x_)
to be an identifier. That seems like a reasonable restriction since it's easy to give an ftype a name and easier to use when it has one. You're also correct that actual parameters for arguments declared as void*
aren't automatically cast, which would be a welcome extension.
Consider the following example program:
It works but is very weakly typed as we supply fixnums as argument for the foreign function: Supplying
a-addr
andb-addr
instead ofa
andb
circumvents the type checks. To strengthen the checks I expected that all of the following three variations are valid. They are however rejected as invalid.In my opinion this would be a valuable addition to the beautiful Chez ftype interface. 1) Would be neat as it would allow to declare pointer to pointers correctly. Currently only base types do seem to be supported. 2) Is a bit of a hack as it mimics the behavior of C but not that of C++. 3) Seems to be quite nice as it allows to explicitly cast any pointer to void* which is a useful and proven idiom.
Any thoughts on this?