FFI and when to convert the stack pointer (an Alien) into an ExternalAddress

Previous Topic Next Topic
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

FFI and when to convert the stack pointer (an Alien) into an ExternalAddress

Holger Freyther
I am toying with Ben's bindings to clang-c (C interface to the Clang C-indexer API). One of the main features of the C API is a way to visit the translation unit. This is implemented as a callback into Smalltalk with with "cursors" providing indirect access and simplified access to the node of the AST. The return result indicates how to continue the traversal (continue, stop, recurse).

                signature:  #( CXChildVisitResult (
                                                                CXCursor cursor,
                                                                CXCursor parent,
                                                                CXString client_data))
                block: [ :cursor :parent :clientData |
                        cursor spelling. <- booom but no crash
                  aCXChildVisitResult value "@1" ].

"cursor" will be an Instance of CXCursor and is passed by value and the C struct size is >16 bytes (on Unix this is passed on the stack). The resulting CXCursor has a handle that is invalid to perform any call-out with.

  CXCursor getHandle
                handle: an Alien (isPointer = true, the stack ptr
                offset: 0

ExternalStructure defines valid types as ByteArray (the data) or ExternalAddress (the pointer). FFIExternalStructureReferenceHandle is missing there and I will create a separate thread/ticket about it.

So somewhere from:


ee will need to convert the handle + offset (one based) to an ExternalAddress. Now the protocol of >>#handle:at: and >>#integerAt:, >>#pointerAt: indicate that we want to carry address+offset into late of the conversion. And I can't point my finger into where it should be done.

I have created:

Alien>>#referenceStructAt: byteOffset length: length
        ^self isPointer
                ifFalse: [super referenceStructAt: byteOffset length: length ]
                ifTrue: [ (ExternalAddress fromAddress: self addressField) + (byteOffset - 1)]

This "fixes" it. But that is at the last point in the conversion. It shadows another problem as well.

So in fact maybe changing:

FFICallbackArgumentReader>>#extractPointerOfType: and >>#extractStructType: to read:

        pair := self nextBaseAddressForStructure: type.
        baseAddressToRead := ExternalAddress fromAddress: pair first address. <- modified
        offsetOfBaseAddress := pair second.


is this the right way forward? We convert the stack to an ExternalAddress early on and use it.

With the above change to FFICallbackArgumentReader the CXCursor from the stack will read as:

  CXCursor getHandle
                handle: ExternalAddress
                offset: 0

I am still not able to push this cursor to the stack. But that is for another mail.