[squeak-dev] FFI - structure pointer

John M McIntosh johnmci at smalltalkconsulting.com
Sat Apr 3 18:01:07 UTC 2010

On 2010-04-03, at 6:36 AM, Schwab,Wilhelm K wrote:

> Andreas, John, anybody,
> I need to find the address of a "function" (it is in fact a global structure pointer somewhere in memory) and pass it to another function.

Well some sample code from the objective C bridge. This doesn't use any "C" code or the FFI/Alien logic since it was targeted 
towards the iPhone and FFI and Alien aren't supported. 

This creates a byteArray that contains the (length) bytes from a known global structure identified by linker name. 
However the primitiveGetAddressFromEntryPointString returns a memory address as a large positive integer. 

"Pass in the name in a String, indicate the length of the data element"

fetchByteArrayConstantCalled: aString withLength: length
	| address |
	address := self findAddressForString: aString.
	address = 0 ifTrue: [^self error: 'Address of constant not found'].
	^self fetchByteArrayFrom: address length: length.

findAddressForString: aNameString
	"ObjectiveCBridge findAddressForString: 'CGRectZero'"

	| externalAddress |

	externalAddress := self primitiveGetAddressFromEntryPointString: aNameString.

primitiveGetAddressFromEntryPointString: aString
	<primitive: 'primitiveGetAddressFromEntryPointString' module: 'ObjectiveCPlugin'>
	self primitiveFailed

"The plugin code is below, first we need to move the name from a smalltalk string to a C String. To 
do this we construct a strlcpy  using a fake call to str:l:cpy:   then we invoke dl:sym:  which is really dlSym(-2,entryPointName) 
This gives back the address of the data. Remember to create a 64bit positive number out of it since we could be on a 64bit system

primitiveGetAddressFromEntryPointString: aEntryPointName
	| entryPointNameLength fn entryPointName  |
	self primitive: 'primitiveGetAddressFromEntryPointString'
		parameters: #(String).

	self var: 'entryPointName' declareC: 'char entryPointName[256]'.
	self var: 'fn' declareC: 'void * fn'.
	entryPointNameLength := interpreterProxy slotSizeOf: aEntryPointName cPtrAsOop.
	entryPointNameLength > 256 ifTrue: [^interpreterProxy positive64BitIntegerFor: 0].
	self str: entryPointName l: aEntryPointName cpy: entryPointNameLength+1.
	fn  := self dl: -2 sym: entryPointName.
	^interpreterProxy positive64BitIntegerFor: (self cCoerce: fn to: 'usqInt') 

"Given an address lets fetch N bytes from it, the ByteArray is create by the primitive "

fetchByteArrayFrom: anAddress length: length
	^self nsInvocationGetStructureType: anAddress length: length

nsInvocationGetStructureType: bufferAddressOop length: length
	^self primitiveNSInvocationGetStructureType: bufferAddressOop length: length

primitiveNSInvocationGetStructureType: bufferAddressOop length: length
	<primitive: 'primitiveNSInvocationGetStructureType' module: 'ObjectiveCPlugin'>
	self primitiveFailed

"64bits again for 64 bit systems,  Use the fake construct of me:m:cpy: to do the memcpy"

primitiveNSInvocationGetStructureType: bufferAddressOop length: length
	|  bufferPointer newByteArray |
	self primitive: 'primitiveNSInvocationGetStructureType'
		parameters: #(Oop SmallInteger).
	self var: 'bufferPointer' declareC: 'char ** bufferPointer'.
	self var: 'buffer' declareC: 'char * buffer'.

	bufferPointer := self cCoerce: (interpreterProxy positive64BitValueOf: bufferAddressOop) to: 'void *'.
	interpreterProxy failed ifTrue: [^nil].
	newByteArray := interpreterProxy
		instantiateClass: interpreterProxy classByteArray
		indexableSize: length.
	self me: (interpreterProxy arrayValueOf: newByteArray)
		m: bufferPointer
		cpy: length. "void * memcpy(void *restrict s1, const void *restrict s2, size_t n)"

John M. McIntosh <johnmci at smalltalkconsulting.com>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2445 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20100403/a7dd5373/smime.bin

More information about the Squeak-dev mailing list