FFI - structure pointer

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

FFI - structure pointer

Schwab,Wilhelm K
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.

Suppose the structure is called Type and the function allocate_one().  I call the function something like

allocateOne:type size:anInt
  <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long ) >


but I am having an awful time getting the pointer to Type.  Given that dlsym() will return a pointer to it, how can I represent that in Smalltalk?  I have tried variations on

  "Indirectly call dlsym()"
  address := Library default getProcAddress:'name_of_global_struct'.

  "try to create Type* from the resulting address"
  type := Type fromHandle:address.
  type := Type fromHandle:address getHandle.
  type := ExternalData fromHandle:address type:Type externalType asPointerType.

  Something := Library default allocateOne:type size:2.

and it either complains about bad arguments during the call or segment faults.  Any ideas or similar examples?

Bill


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: FFI - structure pointer

Andreas.Raab
On 4/3/2010 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.
>
> Suppose the structure is called Type and the function allocate_one().  I call the function something like
>
> allocateOne:type size:anInt
>    <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )>
>
>
> but I am having an awful time getting the pointer to Type.  Given that dlsym() will return a pointer to it, how can I represent that in Smalltalk?  I have tried variations on
>
>    "Indirectly call dlsym()"
>    address := Library default getProcAddress:'name_of_global_struct'.
>
>    "try to create Type* from the resulting address"
>    type := Type fromHandle:address.
>    type := Type fromHandle:address getHandle.
>    type := ExternalData fromHandle:address type:Type externalType asPointerType.
>
>    Something := Library default allocateOne:type size:2.
>
> and it either complains about bad arguments during the call or segment faults.  Any ideas or similar examples?

The return type of getProcAddress: is likely wrong. It should be
declared to return void* which will cause it to return an ExternalData.
With an ExternalData your second variant "Type fromHandle: data
getHandle" will work.

Cheers,
   - Andreas

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: FFI - structure pointer

Schwab,Wilhelm K
Andreas,

#getProcAddress: is a Smalltalk message, so it does not have a return type.  It does return an ExternalData because it it ultimately calls

 <cdecl: void* 'FindSymbol' ( long char* ) >

I had to create FindSymbol as a simply wrapper around dlsym() because the vm dies a quick death over (what I believe to be) linking hassles similar to recent problems in skype.  Of course, I am referring the Linux vm or I would be calling GetProcAddress().

One thing that I considered is that the aspects of the ExternalData might be incorrect.  The handle is an external address and type is an ExternalType that prints itself as void*.  With many variations, if the call was made, the vm crashed.

Bill


-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of Andreas Raab
Sent: Saturday, April 03, 2010 11:54 AM
To: The general-purpose Squeak developers list
Cc: [hidden email]
Subject: Re: [Pharo-project] FFI - structure pointer

On 4/3/2010 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.
>
> Suppose the structure is called Type and the function allocate_one().  
> I call the function something like
>
> allocateOne:type size:anInt
>    <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )>
>
>
> but I am having an awful time getting the pointer to Type.  Given that
> dlsym() will return a pointer to it, how can I represent that in
> Smalltalk?  I have tried variations on
>
>    "Indirectly call dlsym()"
>    address := Library default getProcAddress:'name_of_global_struct'.
>
>    "try to create Type* from the resulting address"
>    type := Type fromHandle:address.
>    type := Type fromHandle:address getHandle.
>    type := ExternalData fromHandle:address type:Type externalType asPointerType.
>
>    Something := Library default allocateOne:type size:2.
>
> and it either complains about bad arguments during the call or segment faults.  Any ideas or similar examples?

The return type of getProcAddress: is likely wrong. It should be declared to return void* which will cause it to return an ExternalData.
With an ExternalData your second variant "Type fromHandle: data getHandle" will work.

Cheers,
   - Andreas

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] FFI - structure pointer

johnmci
In reply to this post by Schwab,Wilhelm K

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 <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================





_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

smime.p7s (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: FFI - structure pointer

Andreas.Raab
In reply to this post by Schwab,Wilhelm K
On 4/3/2010 10:10 AM, Schwab,Wilhelm K wrote:
> Andreas,
>
> #getProcAddress: is a Smalltalk message, so it does not have a return type.  It does return an ExternalData because it it ultimately calls
>
>   <cdecl: void* 'FindSymbol' ( long char* )>
>
> I had to create FindSymbol as a simply wrapper around dlsym() because the vm dies a quick death over (what I believe to be) linking hassles similar to recent problems in skype.  Of course, I am referring the Linux vm or I would be calling GetProcAddress().
>
> One thing that I considered is that the aspects of the ExternalData might be incorrect.  The handle is an external address and type is an ExternalType that prints itself as void*.  With many variations, if the call was made, the vm crashed.

Can you verify the correctness of both pointer as well as function
signature? Depending on platform and/or entity in question you just
*might* get an extra indirection.

If you can't get the code to work as-is I would recommend compiling your
own library that exports a symbol in the form you're using and then
verify correctness of the bridge that way.

Cheers,
   - Andreas

> -----Original Message-----
> From: [hidden email] [mailto:[hidden email]] On Behalf Of Andreas Raab
> Sent: Saturday, April 03, 2010 11:54 AM
> To: The general-purpose Squeak developers list
> Cc: [hidden email]
> Subject: Re: [Pharo-project] FFI - structure pointer
>
> On 4/3/2010 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.
>>
>> Suppose the structure is called Type and the function allocate_one().
>> I call the function something like
>>
>> allocateOne:type size:anInt
>>     <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )>
>>
>>
>> but I am having an awful time getting the pointer to Type.  Given that
>> dlsym() will return a pointer to it, how can I represent that in
>> Smalltalk?  I have tried variations on
>>
>>     "Indirectly call dlsym()"
>>     address := Library default getProcAddress:'name_of_global_struct'.
>>
>>     "try to create Type* from the resulting address"
>>     type := Type fromHandle:address.
>>     type := Type fromHandle:address getHandle.
>>     type := ExternalData fromHandle:address type:Type externalType asPointerType.
>>
>>     Something := Library default allocateOne:type size:2.
>>
>> and it either complains about bad arguments during the call or segment faults.  Any ideas or similar examples?
>
> The return type of getProcAddress: is likely wrong. It should be declared to return void* which will cause it to return an ExternalData.
> With an ExternalData your second variant "Type fromHandle: data getHandle" will work.
>
> Cheers,
>     - Andreas


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] FFI - structure pointer

johnmci
In reply to this post by johnmci

On 2010-04-03, at 11:01 AM, John M McIntosh wrote:

> entryPointNameLength > 256 ifTrue: [^interpreterProxy positive64BitIntegerFor: 0].

Tsk, should be > 255
--
===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================





_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

smime.p7s (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: FFI - structure pointer

Schwab,Wilhelm K
In reply to this post by Andreas.Raab
Andreas,

I *think* I already took your second option.  I created functions that do nothing but return the structure pointer, call them and pass the result onward - it seems to work.

Bill




-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of Andreas Raab
Sent: Saturday, April 03, 2010 1:16 PM
To: The general-purpose Squeak developers list
Cc: [hidden email]
Subject: Re: [Pharo-project] FFI - structure pointer

On 4/3/2010 10:10 AM, Schwab,Wilhelm K wrote:

> Andreas,
>
> #getProcAddress: is a Smalltalk message, so it does not have a return
> type.  It does return an ExternalData because it it ultimately calls
>
>   <cdecl: void* 'FindSymbol' ( long char* )>
>
> I had to create FindSymbol as a simply wrapper around dlsym() because the vm dies a quick death over (what I believe to be) linking hassles similar to recent problems in skype.  Of course, I am referring the Linux vm or I would be calling GetProcAddress().
>
> One thing that I considered is that the aspects of the ExternalData might be incorrect.  The handle is an external address and type is an ExternalType that prints itself as void*.  With many variations, if the call was made, the vm crashed.

Can you verify the correctness of both pointer as well as function signature? Depending on platform and/or entity in question you just
*might* get an extra indirection.

If you can't get the code to work as-is I would recommend compiling your own library that exports a symbol in the form you're using and then verify correctness of the bridge that way.

Cheers,
   - Andreas

> -----Original Message-----
> From: [hidden email]
> [mailto:[hidden email]] On Behalf Of
> Andreas Raab
> Sent: Saturday, April 03, 2010 11:54 AM
> To: The general-purpose Squeak developers list
> Cc: [hidden email]
> Subject: Re: [Pharo-project] FFI - structure pointer
>
> On 4/3/2010 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.
>>
>> Suppose the structure is called Type and the function allocate_one().
>> I call the function something like
>>
>> allocateOne:type size:anInt
>>     <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )>
>>
>>
>> but I am having an awful time getting the pointer to Type.  Given
>> that
>> dlsym() will return a pointer to it, how can I represent that in
>> Smalltalk?  I have tried variations on
>>
>>     "Indirectly call dlsym()"
>>     address := Library default getProcAddress:'name_of_global_struct'.
>>
>>     "try to create Type* from the resulting address"
>>     type := Type fromHandle:address.
>>     type := Type fromHandle:address getHandle.
>>     type := ExternalData fromHandle:address type:Type externalType asPointerType.
>>
>>     Something := Library default allocateOne:type size:2.
>>
>> and it either complains about bad arguments during the call or segment faults.  Any ideas or similar examples?
>
> The return type of getProcAddress: is likely wrong. It should be declared to return void* which will cause it to return an ExternalData.
> With an ExternalData your second variant "Type fromHandle: data getHandle" will work.
>
> Cheers,
>     - Andreas


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] FFI - structure pointer

Schwab,Wilhelm K
In reply to this post by johnmci
John,

Sorry, but you lost me.  When I see interpreter proxies, I think of plugins, which I'm not doing.  Are you asking me to check something?

Bill




-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of John M McIntosh
Sent: Saturday, April 03, 2010 1:22 PM
To: [hidden email]
Cc: [hidden email]; The general-purpose Squeak developers list
Subject: Re: [Pharo-project] [squeak-dev] FFI - structure pointer


On 2010-04-03, at 11:01 AM, John M McIntosh wrote:

> entryPointNameLength > 256 ifTrue: [^interpreterProxy positive64BitIntegerFor: 0].

Tsk, should be > 255
--
===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================





_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] FFI - structure pointer

johnmci
Well you were showing "C" last time around so I assumed you where doing everything by hand so to speak.
Anyway the example shows how to get a memory address of a linker exposed global symbol without help from FFI/Alien/VM

On 2010-04-03, at 11:54 AM, Schwab,Wilhelm K wrote:

> John,
>
> Sorry, but you lost me.  When I see interpreter proxies, I think of plugins, which I'm not doing.  Are you asking me to check something?
>
> Bill

--
===========================================================================
John M. McIntosh <[hidden email]>   Twitter:  squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================





_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

smime.p7s (3K) Download Attachment