Hi,
try with this:
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) )
library: 'Ws2_32.dll'. "... on Windows"
From Playground, you can then do:
| name len |
len := 50.
name:= ByteArray new: len.
FFITutorial new getHostNameInto: name ofLenght: len.
name inspect.
I hope this helps.
Best wishes,
Tomaz
Hi,
Thanks for the example. Unfortunately, it doesn't work on Linux.
Thanks,
Gerry
From: Tomaž Turk tomaz.turk@ef.uni-lj.si
Sent: Sunday, November 28, 2021 11:39 AM
To: Any question about pharo is welcome pharo-users@lists.pharo.org
Subject: [Pharo-users] Re: uFFI provide buffer to C
Hi,
try with this:
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) ) library: 'Ws2_32.dll'. "... on Windows"
From Playground, you can then do:
| name len |
len := 50.
name:= ByteArray new: len.
FFITutorial new getHostNameInto: name ofLenght: len.
name inspect.
I hope this helps.
Best wishes,
Tomaz
Hi Gerry,
I think the point of Tomaz is that an FFI method can only have a single #ffiCall: statement.
In your example, what you can do is to split your method in two methods:
First a method with the mapping (following the idea of Tomaz but using libc)
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) ) library: 'libc.so.6'.
And then have a second method that calls this one:
FFITutorial>>getHostName
| nameBuffer |
nameBuffer := ByteArray new: 256.
self getHostNameInto: nameBuffer ofLenght: 256.
^nameBuffer asString
Notice that converting the byte array buffer to string will only work by chance if the called function returns characters encoded in ascii.
In Pharo strings are Unicode characters where each character is a unicode code-point.
The best thing is to read the documentation of the library and check the encoding of the string that is put in the buffer to decode it accordingly, for example from utf8.
G
El 29 nov 2021, a las 0:56, Gerry Weaver gerryw@compvia.com escribió:
Hi,
Thanks for the example. Unfortunately, it doesn't work on Linux.
Thanks,
Gerry
From: Tomaž Turk tomaz.turk@ef.uni-lj.si
Sent: Sunday, November 28, 2021 11:39 AM
To: Any question about pharo is welcome pharo-users@lists.pharo.org
Subject: [Pharo-users] Re: uFFI provide buffer to C
Hi,
try with this:
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) ) library: 'Ws2_32.dll'. "... on Windows"
From Playground, you can then do:
| name len |
len := 50.
name:= ByteArray new: len.
FFITutorial new getHostNameInto: name ofLenght: len.
name inspect.
I hope this helps.
Best wishes,
Tomaz
On 29 Nov 2021, at 10:10, Guillermo Polito guillermopolito@gmail.com wrote:
Hi Gerry,
I think the point of Tomaz is that an FFI method can only have a single #ffiCall: statement.
In your example, what you can do is to split your method in two methods:
First a method with the mapping (following the idea of Tomaz but using libc)
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) ) library: 'libc.so.6'.
And then have a second method that calls this one:
FFITutorial>>getHostName
| nameBuffer |
nameBuffer := ByteArray new: 256.
self getHostNameInto: nameBuffer ofLenght: 256.
^nameBuffer asString
Notice that converting the byte array buffer to string will only work by chance if the called function returns characters encoded in ascii.
In Pharo strings are Unicode characters where each character is a unicode code-point.
In general #utf8Decoded is better than #asString since UTF-8 includes 7-bit ASCII. It will fail when the native encoding is one of the simpler byte encodings, like Latin1 (or iso-8859-1), though.
The best thing is to read the documentation of the library and check the encoding of the string that is put in the buffer to decode it accordingly, for example from utf8.
G
El 29 nov 2021, a las 0:56, Gerry Weaver gerryw@compvia.com escribió:
Hi,
Thanks for the example. Unfortunately, it doesn't work on Linux.
Thanks,
Gerry
From: Tomaž Turk tomaz.turk@ef.uni-lj.si
Sent: Sunday, November 28, 2021 11:39 AM
To: Any question about pharo is welcome pharo-users@lists.pharo.org
Subject: [Pharo-users] Re: uFFI provide buffer to C
Hi,
try with this:
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) ) library: 'Ws2_32.dll'. "... on Windows"
From Playground, you can then do:
| name len |
len := 50.
name:= ByteArray new: len.
FFITutorial new getHostNameInto: name ofLenght: len.
name inspect.
I hope this helps.
Best wishes,
Tomaz
Hi Guillermo,
Ah ok. I didn’t realize that I could only have a single statement. I got it working now.
Thanks to you and everyone that helped me out.
Thanks,
Gerry
Gerry Weaver
(800) 318-6118
From: Guillermo Polito guillermopolito@gmail.com
Sent: Monday, November 29, 2021 3:11 AM
To: Any question about pharo is welcome pharo-users@lists.pharo.org
Subject: [Pharo-users] Re: uFFI provide buffer to C
Hi Gerry,
I think the point of Tomaz is that an FFI method can only have a single #ffiCall: statement.
In your example, what you can do is to split your method in two methods:
First a method with the mapping (following the idea of Tomaz but using libc)
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) ) library: 'libc.so.6'.
And then have a second method that calls this one:
FFITutorial>>getHostName
| nameBuffer |
nameBuffer := ByteArray new: 256.
self getHostNameInto: nameBuffer ofLenght: 256.
^nameBuffer asString
Notice that converting the byte array buffer to string will only work by chance if the called function returns characters encoded in ascii.
In Pharo strings are Unicode characters where each character is a unicode code-point.
The best thing is to read the documentation of the library and check the encoding of the string that is put in the buffer to decode it accordingly, for example from utf8.
G
El 29 nov 2021, a las 0:56, Gerry Weaver <gerryw@compvia.commailto:gerryw@compvia.com> escribió:
Hi,
Thanks for the example. Unfortunately, it doesn't work on Linux.
Thanks,
Gerry
From: Tomaž Turk <tomaz.turk@ef.uni-lj.simailto:tomaz.turk@ef.uni-lj.si>
Sent: Sunday, November 28, 2021 11:39 AM
To: Any question about pharo is welcome <pharo-users@lists.pharo.orgmailto:pharo-users@lists.pharo.org>
Subject: [Pharo-users] Re: uFFI provide buffer to C
Hi,
try with this:
FFITutorial>>getHostNameInto: hostName ofLenght: length
^self ffiCall: #( int gethostname(char *hostName, int length) ) library: 'Ws2_32.dll'. "... on Windows"
From Playground, you can then do:
| name len |
len := 50.
name:= ByteArray new: len.
FFITutorial new getHostNameInto: name ofLenght: len.
name inspect.
I hope this helps.
Best wishes,
Tomaz