[Pharo-project] Native Boost Basics: passing char* buffer
I am trying to work with memory addresses back n forth.. Simple case of char* buffer that needs to be filled in by dll . Buffer does not change in Pharo after the call. Am I missing something here.. The memory address that is printed out does not match what I see in Pharo / infact the address does not change at all... for repeated call invoked from debugger. C Code: DLLEXPORT int readAndWritePipe(char* outBuf ) { system("Echo readAndWritePipe" ); debugPrintf ( "readAndWritePipe: %d \n" , &outBuf , 1046 ); memcpy ( outBuf , "Testing123\0" , 11) ; return 0; } void debugPrintf ( char* logString, int intArg , char* strArg, int size ) { // can redirect as needed to logger end point.. FILE * logFile = fopen( "c:\\temp\\writePipes.log" , "a" ); char* buf = (char*) calloc( sizeof(char) , size ); sprintf( buf, logString , intArg , strArg ); fputs(buf , logFile ); fclose(logFile); } Pharo: testPharoBuffer: buf <primitive: #primitiveNativeCall module: #NativeBoostPlugin error: errorCode > ^ self nbCall: #( int readAndWritePipe( String buf ) ) module: 'TestPharo.dll' testPharoBuffer "self new testPharoBuffer " | buf addr addr2 | buf := String new: 100000. addr := buf asNBExternalString. addr2 := ( NativeBoost allocate: 256 ). self testPharoBuffer: addr . " or use addr2, both of it does not work" Transcript cr; show: buf.
On 1 January 2013 07:43, S Krish <krishnamachari.sudhakar@gmail.com> wrote:
I am trying to work with memory addresses back n forth..
Simple case of char* buffer that needs to be filled in by dll . Buffer does not change in Pharo after the call. Am I missing something here..
The memory address that is printed out does not match what I see in Pharo / infact the address does not change at all... for repeated call invoked from debugger.
C Code:
DLLEXPORT int readAndWritePipe(char* outBuf ) { system("Echo readAndWritePipe" ); debugPrintf ( "readAndWritePipe: %d \n" , &outBuf , 1046 ); memcpy ( outBuf , "Testing123\0" , 11) ; return 0; }
are you sure you want to print an address of argument (&outBuf) instead of argument value (outBuf - which is a pointer value passed to function) ? Because &outBuf, will always be a location on stack where the value stored. And sure thing, when you call that function from simple short test app, it will be always same, since nothing interferes with stack.
void debugPrintf ( char* logString, int intArg , char* strArg, int size ) { // can redirect as needed to logger end point.. FILE * logFile = fopen( "c:\\temp\\writePipes.log" , "a" ); char* buf = (char*) calloc( sizeof(char) , size ); sprintf( buf, logString , intArg , strArg ); fputs(buf , logFile ); fclose(logFile); }
Pharo:
testPharoBuffer: buf
<primitive: #primitiveNativeCall module: #NativeBoostPlugin error: errorCode > ^ self nbCall: #( int readAndWritePipe( String buf ) ) module: 'TestPharo.dll'
testPharoBuffer "self new testPharoBuffer " | buf addr addr2 | buf := String new: 100000. addr := buf asNBExternalString. addr2 := ( NativeBoost allocate: 256 ). self testPharoBuffer: addr . " or use addr2, both of it does not work" Transcript cr; show: buf.
String type in signature makes a copy of string on stack + adds null-terminating character, and then pushing the pointer on stack as argument to function. So, it is more like 'pass by value-copy' argument. If you want to do 'pass by reference', just use 'void *' (or char* ) in function signature, but then make sure you null-terminate stuff there by yourself, if needed. String type converter is more for convenience to avoid dealing with null-terminating chars every time. But sure thing, if you need to pass a pointer to buffer, where function will store something ,you should not use it. -- Best regards, Igor Stasenko.
testPharoBuffer "self new testPharoBuffer " | buf addr addr2 | buf := String new: 100000. addr := buf asNBExternalString. addr2 := ( NativeBoost allocate: 256 ). self testPharoBuffer: addr . " or use addr2, both of it does not work" Transcript cr; show: buf. have tried "addr readString" / on addr2 .. too Need to understand how to pass a memory location to the dll function stack and get back what is written to the memory in Pharo in a more general sense. On Tue, Jan 1, 2013 at 12:13 PM, S Krish <krishnamachari.sudhakar@gmail.com>wrote:
I am trying to work with memory addresses back n forth..
Simple case of char* buffer that needs to be filled in by dll . Buffer does not change in Pharo after the call. Am I missing something here..
The memory address that is printed out does not match what I see in Pharo / infact the address does not change at all... for repeated call invoked from debugger.
C Code:
DLLEXPORT int readAndWritePipe(char* outBuf ) { system("Echo readAndWritePipe" ); debugPrintf ( "readAndWritePipe: %d \n" , &outBuf , 1046 ); memcpy ( outBuf , "Testing123\0" , 11) ; return 0; }
void debugPrintf ( char* logString, int intArg , char* strArg, int size ) { // can redirect as needed to logger end point.. FILE * logFile = fopen( "c:\\temp\\writePipes.log" , "a" ); char* buf = (char*) calloc( sizeof(char) , size ); sprintf( buf, logString , intArg , strArg ); fputs(buf , logFile ); fclose(logFile); }
Pharo:
testPharoBuffer: buf
<primitive: #primitiveNativeCall module: #NativeBoostPlugin error: errorCode > ^ self nbCall: #( int readAndWritePipe( String buf ) ) module: 'TestPharo.dll'
testPharoBuffer "self new testPharoBuffer " | buf addr addr2 | buf := String new: 100000. addr := buf asNBExternalString. addr2 := ( NativeBoost allocate: 256 ). self testPharoBuffer: addr . " or use addr2, both of it does not work" Transcript cr; show: buf.
On 1 January 2013 09:39, S Krish <krishnamachari.sudhakar@gmail.com> wrote:
testPharoBuffer "self new testPharoBuffer " | buf addr addr2 | buf := String new: 100000. addr := buf asNBExternalString. addr2 := ( NativeBoost allocate: 256 ). self testPharoBuffer: addr . " or use addr2, both of it does not work" Transcript cr; show: buf.
have tried "addr readString" / on addr2 .. too
Need to understand how to pass a memory location to the dll function stack and get back what is written to the memory in Pharo in a more general sense.
Hmm.. Did you changed the signature? self nbCall: #( int readAndWritePipe( void * buf ) ) module: 'TestPharo.dll' So, if this a String (a variable-byte object) , a function will receive a pointer to its first byte, and if its address (NBExternalAddress) then a pointer passed to function will be equal to that address.
On Tue, Jan 1, 2013 at 12:13 PM, S Krish <krishnamachari.sudhakar@gmail.com> wrote:
I am trying to work with memory addresses back n forth..
Simple case of char* buffer that needs to be filled in by dll . Buffer does not change in Pharo after the call. Am I missing something here..
The memory address that is printed out does not match what I see in Pharo / infact the address does not change at all... for repeated call invoked from debugger.
C Code:
DLLEXPORT int readAndWritePipe(char* outBuf ) { system("Echo readAndWritePipe" ); debugPrintf ( "readAndWritePipe: %d \n" , &outBuf , 1046 ); memcpy ( outBuf , "Testing123\0" , 11) ; return 0; }
void debugPrintf ( char* logString, int intArg , char* strArg, int size ) { // can redirect as needed to logger end point.. FILE * logFile = fopen( "c:\\temp\\writePipes.log" , "a" ); char* buf = (char*) calloc( sizeof(char) , size ); sprintf( buf, logString , intArg , strArg ); fputs(buf , logFile ); fclose(logFile); }
Pharo:
testPharoBuffer: buf
<primitive: #primitiveNativeCall module: #NativeBoostPlugin error: errorCode > ^ self nbCall: #( int readAndWritePipe( String buf ) ) module: 'TestPharo.dll'
testPharoBuffer "self new testPharoBuffer " | buf addr addr2 | buf := String new: 100000. addr := buf asNBExternalString. addr2 := ( NativeBoost allocate: 256 ). self testPharoBuffer: addr . " or use addr2, both of it does not work" Transcript cr; show: buf.
-- Best regards, Igor Stasenko.
participants (2)
-
Igor Stasenko -
S Krish