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. ^externalAddress 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)" ^newByteArray -- =========================================================================== John M. McIntosh <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ===========================================================================