[Vm-dev] Alien/FFI issue with large struct passed as value and how to load vmmaker?

Holger Freyther holger at freyther.de
Thu Apr 4 17:04:05 UTC 2019

> On 3. Apr 2019, at 23:50, Eliot Miranda <eliot.miranda at gmail.com> wrote:
> Hi Holger,

> It's represented as FFIExternalStructure subclass: #CXCursor. In the case of the callback the handle is an instance of FFIExternalStructureReferenceHandle with an Alien embedded into it.
> What is the C signature of the callback function, and what is the source of the marshaling method in the relevant Callback subclass's signatures protocol?
> Also, what's the callout's signature and what is the Smalltalk code for the call?

C declaration:

typedef enum CXChildVisitResult(* CXCursorVisitor) (CXCursor cursor, CXCursor parent, CXClientData client_data);

and passed to the c function below.

unsigned clang_visitChildren 	(CXCursor parent, CXCursorVisitor visitor,  CXClientData client_data );

Smalltalk Source:

	acceptCallbackFn := 
		signature:  #( CXChildVisitResult (
								CXCursor cursor, 
								CXCursor parent, 
								CXString client_data))

CXChildVisitResult is an enum, CXCursor/CXString are FFIExternalStructure subclasses.

Smalltalk code:

	Libclang clang_visitChildren__parentCursor: rootCursor 
	                           visitorCallback: acceptCallbackFn 
	                                clientData: rootClientData.

>>#clang_visitChildren__parentCursor: parent 
                  visitorCallback: visitor 
                       clientData: client_data
	^ self ffiCall: #( uint clang_visitChildren(
	 							CXCursor parent,
								CXCursorVisitor visitor,
				 				CXClientData client_data))

> Or do I chase it from the wrong end?
> Without the code I can't help, hence my questions above.

The full code is in Ben's LibclangPractice (http://smalltalkhub.com/#!/~BenComan/LibclangPractice). I have set a breakpoint in LibclangTest>>#visitChildrenCallbackReturning: to look at the cursor variable and call it's methods. I think my  Pharo PR (https://github.com/pharo-project/pharo/pull/3136/files#diff-8f4b31166c3a817dd8ad1f0518ae633a) is fixing the callback handling in Unified-FFI.

I think I have stumbled into three separate bugs and I just noticed that they are Pharo specific. Unified-FFI doesn't seem to exist for Squeak.

1st) an Alien ending inside a handle of a FFIExternalStructure sub-instance. I have made a PR for it and I think it is reasonable to turn the Alien into an ExternalAddress early.

2nd) Pushing a FFIExternalStructure sub-instance with a FFIExternalStructureReferenceHandle in it to the stack doesn't work. Squeak+ThreadedFFIPlugin simply don't know what a FFIExternalStructureReferenceHandle valueOOP is.

3rd) Returning a struct from the callback doesn't to work either. That's a UnifiedFFI bug as well:

In FFICallbackParameterTests>>#testPassingStructureInTheStack 
	| param |
	callback := FFICallback 
		signature: #(int (FFITestStructureSmallIntFloatStructure a))
		block: [ :a |
			self assert: a x equals: 2.0. 
			self assert: a y equals: 3. ..

change the "int" to "FFITestStructureSmallIntFloatStructure" and the first assertion will fail. The value of "a x" becomes 3. I have not debugged this.

I think only 2nd) is relevant to this list. Support for FFIExternalStructureReferenceHandle will add one level of indirection.

More information about the Vm-dev mailing list