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

Steve Rees squeak-vm-dev at vimes.worldonline.co.uk
Sun May 16 01:58:04 UTC 2010


Hi Joachim,

On 15/05/2010 22:16, stephane ducasse wrote:
> From: Joachim Geidel <joachim.geidel at onlinehome.de>
>> Date: May 15, 2010 10:57:37 PM GMT+02:00
>> To: pharo-users at lists.gforge.inria.fr
>> Subject: [Pharo-users] Need help with Alien, unexpected function return value
>> Reply-To: A friendly place where any question about pharo is welcome<pharo-users at lists.gforge.inria.fr>
>>
>>
>> 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



More information about the Vm-dev mailing list