[Pharo-users] Pumping FFI documentation [WAS] FFI beginner question

eftomi tomaz.turk at ef.uni-lj.si
Tue Sep 24 16:07:03 EDT 2019

Hi Guille,

Thanks for your efforts, we really appreciate it! 

I was intrigued by Stephan and tried to prepare something for the book, like
a subtitle/small chapter "Exotic types", but then I noticed that you already
put some additional content to the book on GitHub since the pdf at pharo.org
was created last year - the text that cleared some of my challenges.

I went through UFFI complexities over and over with the debugger, so I have
relatively good picture of what is going on when a call is "converted" to
bytecode, however I'm constantly finding new pearls inside. UFFI is really
great and heavy package! 

Anyways, I don't think that I can add anything substantial to the content of
the book, however I can help with the feedback and suggestions, I can also
test the examples if you need.

As for the "missing pieces & understandable", I will fire right away :-)
Most of my FFI experiences are coming from fiddling with the "mysterious"
Win32WideString implementation or wchar_t*, char16_t*, char32_t* … family of
wide strings on Windows. It seems to me that Win32WideString class is only
half made, or maybe it was made before UFFI -> I'm just guessing, however
it's a subclass of ExternalObject and not the subclass of FFIExternalObject.
When you pass it through UFFI as an argument, everything is OK, however when
it is returned from a function call it is not automagically treated as a
proper Win32WideString - you have to "manually" convert the data at the
ExternalAddress. And now my suggestions on the book :-)

- I hardly found (on the net, Pharo books ...) any explanation on
ExternalObject's handle, which is quite often used in FFIExternalObjects,
too; what's the difference between a handle and a pointer, and what exactly
the various implementations of #fromHandle: are supposed to do. #fromHandle
is now mentioned in the book, based on  this discussion
<http://forum.world.st/UFFI-correct-way-to-cast-void-td5067008.html>   about
casting, however if you are dealing with an "exotic type" then it would be
nice to have some guidelines about the purpuse of it. To illustrate, in
Win32WideString the handle is implemented as a ByteArray with the data
itself, in other objects that I know of it's normally an (external)
address/pointer, huh?

- When the UFFI call ends, and the return argument's value is put onto the
stack right after the #send:invokeWithArguments:, what happens with that
value - is there anything that can be done with it - can the "casting" be
performed "automatically"? Of course one can always prepare a "wrapper" to
do that, however … I found FFIExternalType>>#emitReturnArgument:context:
where "loader" gets onto the scene, but this leads to heavy lifting with
bytecodes, is I understand :-)

- In relation to that, there is a bit vague explanation in the book about
objects under the title External Objects ("... But often, frameworks will
allocate structures, pointers, etc. which actually represents ”an object”
(not in the same sense as a Smalltalk object, but can be interpreted like
one) ..."). This "interpretation" is a kind of mysterious :-) A couple of
suggestions about possible directions would be nice to have.

- As far as I can see, the FFIExternalValueHolder is not mentioned in the
book yet. It is nicely described in its comment, however the missing
information is that the type (the resulting subclass of
FFIExternalValueHolder) should be defined as a class variable - without that
the signature parser cannot find it. The purpose of FFIExternalValueHolder 
is similar to FFIExternalType class>>#newBuffer.

I hope you find these suggestions helpful.

Best wishes,

Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

More information about the Pharo-users mailing list