Referring to the example show_clang_version() below, cleanup is done with clang_disposeString(). How does UFFI hook into the object finalisation mechanism to call this when the object is garage collected. My searches result mostly in info on weak collections and its not clear how this translates to FFI. Some detail on this would be useful for the FFI manual . cheers -ben On Thu, Sep 1, 2016 at 12:59 AM, Ben Coman <btc@openinworld.com> wrote:
For this definition pulled from a library header file... typedef struct { const void *data; unsigned private_flags; } CXString;
which is used with a helper function to get a usable string like... void show_clang_version(void) { CXString version = clang_getClangVersion(); printf("%s\n", clang_getCString(version)); clang_disposeString(version); }
==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)'
So I defined... FFIExternalStructure subclass: #CXString instanceVariableNames: '' classVariableNames: '' package: 'LibCLang'
and ignoring the const as advised in the manual [1], I try... CXString class >> fieldsDesc ^ #( void *data; unsigned private_flags; )
but... CXString rebuildFieldAccessors. ==>Error: Unable to resolve external type: unsigned
I also tried "unsigned int private_flags;" but get the same error. Any ideas what is wrong?
Actually I can kind of ignore creating accessors since this is like an opaque type where I'm not expected to access its internals, but I do need CXString as a return value like this...
LibCLang class >> getClangVersion ^ self ffiCall: #( CXString clang_getClangVersion () ) module: LibCLang
which needs to be passed to this function to get a workable string....
LibCLang class >> getString: aCXString ^ self ffiCall: #( String clang_getCString ( CXString aCXString ) ) module: LibCLang
However this doesn't work if I use FFIOpaqueObject instead of FFIExternalStructure. I guess the difference is opaque objects are normally pointers to a type, whereas here that pointer is contained in a struct.
What I've done at the moment to push ahead with experimenting is avoid needing to generate accessors by adding...
CXString >> printOn: asStream self getString printOn: aStream
CXString >> getString ^ self ffiCall: #( String clang_getCString ( CXString self ) ) module: LibCLang
such that... LibCLang getClangVersion "<Print It>" ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)'
Is there a better way to approach this?
cheers -ben
btw, this is in Pharo 5 (Moose 6).
[1] https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgres...