Fwd: [Pharo-users] Need help with Alien, unexpected function return value

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

Fwd: [Pharo-users] Need help with Alien, unexpected function return value

stephane ducasse-2



Begin forwarded message:

> From: Joachim Geidel <[hidden email]>
> Date: May 15, 2010 10:57:37 PM GMT+02:00
> To: [hidden email]
> Subject: [Pharo-users] Need help with Alien, unexpected function return value
> Reply-To: A friendly place where any question about pharo is welcome <[hidden email]>
>
>
> Hello everybody,
>
> I need some help with Alien on Mac OS X 10.6.3 in Pharo 1.0. I am calling a
> function from a vtable struct in the Java Native Interface of the Java VM
> which comes with Mac OS X and which is defined as
>
>    jint ( __stdcall * GetVersion)(JNIEnv * env);
>
> The result type jint is just an alias for int. The Smalltalk method is
>
> ----
> primGetVersion
> | functionPointer result vtablePointer |
> vtablePointer := Alien
> atAddress: self externalData asUnsignedLong
> dataSize: Alien sizeofPointer * self vtableSize.
> functionPointer := Alien forPointer:
> (vtablePointer unsignedLongAt: (4 * Alien sizeofPointer + 1)).
> result := (Alien newGC: 4) pointer.
> functionPointer
> primFFICallResult: result
> with: self asJNIParameter.
> ^result signedIntAt: 1
> ----
>
> functionPointer is the pointer to the GetVersion function.
> The result should be 65542 (16r00010006), which is also what I get when
> calling the function from VisualWorks, but the method answers  -394042288
> (-16r177C9BB0). The "result" Alien has the printString '#[0 0 0 0 6 0 1 0]'
> which suspiciously contains the 1 and the 6 I am looking for, but in the
> wrong places. ;-)
>
> I looked at examples for callouts, which seem to indicate that result should
> be the Alien and not a pointer to it. So I changed the code to
>
> ----
> result := (Alien newC: 4).
> functionPointer
> primFFICallResult: result pointer
> with: self asJNIParameter.
> ^result signedIntAt: 1
> ----
> This didn't really help. The result is now 0 (zero), although the Alien
> prints as #[252 255 255 255 80 15 38 0] which doesn't look like a 0 at first
> sight.
>
> Am I using those Aliens in a correct way? What can I try to debug this?
> If this is too obscure and someone who knows about Aliens would like to have
> a look at the rest of the code, I am willing to send a bunch of Monticello
> packages and instructions for reproducing the problem, but I won't make it
> publicly available yet.
>
> Any help is welcome.
>
> Best regards,
> Joachim Geidel
>
> --
> View this message in context: http://forum.world.st/Need-help-with-Alien-unexpected-function-return-value-tp2218105p2218105.html
> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
>
> _______________________________________________
> Pharo-users mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-users

Reply | Threaded
Open this post in threaded view
|

Re: Fwd: [Pharo-users] Need help with Alien, unexpected function return value

Steve Rees
 
Hi Joachim,

On 15/05/2010 22:16, stephane ducasse wrote:

> From: Joachim Geidel <[hidden email]>
>> Date: May 15, 2010 10:57:37 PM GMT+02:00
>> To: [hidden email]
>> Subject: [Pharo-users] Need help with Alien, unexpected function return value
>> Reply-To: A friendly place where any question about pharo is welcome<[hidden email]>
>>
>>
>> Hello everybody,
>>
>> I need some help with Alien on Mac OS X 10.6.3 in Pharo 1.0. I am calling a
>> function from a vtable struct in the Java Native Interface of the Java VM
>> which comes with Mac OS X and which is defined as
>>
>>     jint ( __stdcall * GetVersion)(JNIEnv * env);
>>
>> The result type jint is just an alias for int. The Smalltalk method is
>>
>> ----
>> primGetVersion
>> | functionPointer result vtablePointer |
>> vtablePointer := Alien
>> atAddress: self externalData asUnsignedLong
>> dataSize: Alien sizeofPointer * self vtableSize.
>> functionPointer := Alien forPointer:
>> (vtablePointer unsignedLongAt: (4 * Alien sizeofPointer + 1)).
>> result := (Alien newGC: 4) pointer.
>> functionPointer
>> primFFICallResult: result
>> with: self asJNIParameter.
>> ^result signedIntAt: 1
>> ----
>>
>> functionPointer is the pointer to the GetVersion function.
>> The result should be 65542 (16r00010006), which is also what I get when
>> calling the function from VisualWorks, but the method answers  -394042288
>> (-16r177C9BB0). The "result" Alien has the printString '#[0 0 0 0 6 0 1 0]'
>> which suspiciously contains the 1 and the 6 I am looking for, but in the
>> wrong places. ;-)
>>      

When you use a pointer alien (which has a size field of zero) as the
return result of a function call, the alien code expects the result from
the alien to be a pointer to some area of memory and replaces the
address field of the result alien with the result returned by the
function call. You're lucky your method returned any result at all
rather than crashing with an access violation - you are dereferencing
whatever sits at 0x00010006.

>> I looked at examples for callouts, which seem to indicate that result should
>> be the Alien and not a pointer to it. So I changed the code to
>>
>> ----
>> result := (Alien newC: 4).
>> functionPointer
>> primFFICallResult: result pointer
>> with: self asJNIParameter.
>> ^result signedIntAt: 1
>> ----
>> This didn't really help. The result is now 0 (zero), although the Alien
>> prints as #[252 255 255 255 80 15 38 0] which doesn't look like a 0 at first
>> sight.
>>      
This time you are returning the signed int at the block of memory
allocated by the newC: call. The memory gets zeroed before use, which is
why you get a zero. Because you used "result pointer" in the alien call
the alien code again replaces the pointer alien's address with the
result. This time though, you don't have a reference to the pointer
alien, so the result is effectively discarded.

Try the following

        result := (Alien new: 4).
        functionPointer
                primFFICallResult: result
                with: self asJNIParameter.
        ^result signedIntAt: 1

Note that I could have used a C alloc'ed alien here, but there is no need.

HTH

Regards, Steve

--
You can follow me on twitter at http://twitter.com/smalltalkhacker