[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 := 
	   FFICallback
		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