I have a type definition...
   typedef void *CXIndex;

which I believe reads "CXIndex is a pointer at void"
that is returned by...
    CXIndex clang_createIndex(int x, int y)

This seems an obvious candidate to be a FFIOpaqueObject defined like this...

  FFIOpaqueObject subclass: #CXIndex
      instanceVariableNames: ''
      classVariableNames: ''
      package: 'LibclangPractice'

  CXIndex class >> create
      ^ self ffiCall: #( CXIndex clang_createIndex ( 0, 0 ) )

however  "CXIndex create inspect"
produces an error ==> FFIDereferencedOpaqueObjectError.
because..."external objects have a natural arity of zero but they MUST be
called with some arity,
because they are actually external addresses (pointers) and you need to
always declare external objects as this example:
   self ffiCall: #( FFIExternalObject *c_function ( FFIExternalObject
*handle ) )
"

which is enforced by...
  FFIOpaqueObjectType>>validateAfterParse: typeAndArityTuple
      self pointerArity >= 1 ifTrue: [ ^ self ].  "@0"
      typeAndArityTuple second >= 1 ifTrue: [ ^ self ].
      FFIDereferencedOpaqueObjectError signal


where pointerArity seems set earlier just by counting the number of pointer
stars in the functions return type, which in this case is none...
  FFICallout>>resolveType: aTypeName   "aTypeName==> 'CXIndex' "
      | name newName resolver binding ptrArity |
      newName := aTypeName.
      ptrArity := 0.
      "resolve aliases and pointers"
      [
            name := newName asString trimRight.
            newName := self aliasForType: name.
            newName last = $* ifTrue: [
                  ptrArity := ptrArity + 1.
                  newName := newName allButLast ].
            name = newName
      ] whileFalse.
      resolver := requestor ifNil: [ self class ].    "resolver==> CXIndex
class"
      binding := resolver ffiBindingOf: name asSymbol.   "binding==>
#CXIndex->CXIndex"
      binding ifNotNil: [
          ^ (binding value "@1" asExternalTypeOn: self) "@2" pointerArity:
ptrArity ] .

which @1 invokes...
  CXIndex(FFIOpaqueObject) class >> asExternalTypeOn: generator
       ^ FFIOpaqueObjectType objectClass: self

  FFIOpaqueObjectType(FFIExternalReferenceType) class >> objectClass: aClass
      ^ self new objectClass: aClass

  FFIOpaqueObjectType(FFIExternalReferenceType) >> objectClass: aClass
objectClass := aClass.    "aClass==>CXIndex"
        pointerArity := 0.  "actually this was done in #initialize"   "@3"


Thus FFIOpaqueObjectType(CXIndex) is returned @2 which invokes...
  FFIOpaqueObjectType(FFIExternalType)>>pointerArity: additionalArity
pointerArity := pointerArity + additionalArity.
which sets pointerArity ==> 0.


But I hazard to suggest that...
    typedef void *CXIndex;

should make pointerArity:=1 when objectClass is assigned @3.


So I hacked around this by....
  FFIExternalReference class >> pointerArity
      ^0

  CXIndex class >> pointerArity
      ^1

  FFIExternalReferenceType >> objectClass: aClass
objectClass := aClass.
pointerArity := aClass pointerArity.

but I wonder if this is the best way, or if external references these
opaque objects should have a class-side method similar to #fieldDesc
like...
    typedef
       ^#( void * )

Thus CXIndex create "==> a CXIndex((void*)@ 16rB6D514A8)"

I am yet to test out this returned object by passing it to another
C-library function, but I thought the above was enough for one sitting.

cheers -ben


P.S. Further background...

Declarations...
    typedef void *CXIndex;
    CXIndex clang_createIndex(int xx, int yy));
defined at...
https://github.com/llvm-mirror/clang/blob/release_39/include/clang-c/Index.h

and definition is at...
https://github.com/llvm-mirror/clang/blob/release_39/include/clang-c/Index.h

   extern "C" {
      CXIndex clang_createIndex(  ) {
           ...
           CIndexer *CIdxr = new CIndexer();
           ...
           return CIndexer;
     } }

Reply via email to