Re: [Pharo-users] FFI return by reference
1) Declare a class variable
MyClass class>>initialize INT_PTR := FFIExternalValueHolder ofType: ?int?.
as a larger explanation, this will create an anonymous subclass to keep ?int? values, than later you can use as a type in your function call. Some people would call this obscure, but is a good way of solving this problem (I adopted it from old NB). If you want to have a named class instead an anonymous class, you can just subclass FFIExternalValueHolder:
FFIExternalValueHolder subclass: #MyIntPtr
and then implement typeDecl class method
MyIntPtr class>>typeDecl ^ ?int'
and this will work as the anonymous class
The second option is definitely what I want. I am trying to expose a function returning several ints, as in SDL2>>mouseStateX: y: (excluding the possibility to return a Point). However I would rather not define my own int holder, can't we have generic holders to rely on? Thibault
On 11 Apr 2016, at 06:24, Thibault Raffaillac <thibault.raffaillac@inria.fr> wrote:
1) Declare a class variable
MyClass class>>initialize INT_PTR := FFIExternalValueHolder ofType: ?int?.
as a larger explanation, this will create an anonymous subclass to keep ?int? values, than later you can use as a type in your function call. Some people would call this obscure, but is a good way of solving this problem (I adopted it from old NB). If you want to have a named class instead an anonymous class, you can just subclass FFIExternalValueHolder:
FFIExternalValueHolder subclass: #MyIntPtr
and then implement typeDecl class method
MyIntPtr class>>typeDecl ^ ?int'
and this will work as the anonymous class
The second option is definitely what I want.
Personally my option would be to put my types in a class pool and use them, not to extend⦠but option is there so you can choose what you want :)
I am trying to expose a function returning several ints, as in SDL2>>mouseStateX: y: (excluding the possibility to return a Point). However I would rather not define my own int holder, can't we have generic holders to rely on?
I will not add for the moment that predefined types value holders⦠We would need to add one for each type we support to be consistent, and document it, and add tests. And btw⦠you do have a generic holder⦠is just that you need to refine it to what you want :) You could always use a ByteArray and took values later (some functions in Athens do it like that). The advantage of this approach (using plain ByteArrays) is that you do not need to change function signature at the cost of needing to do manually what the value holder does for you. My advise is that you go with what you need, we can consider add predefined value holders later. Esteban
Thibault
2016-04-11 15:10 GMT+02:00 Esteban Lorenzano <estebanlm@gmail.com>:
On 11 Apr 2016, at 06:24, Thibault Raffaillac < thibault.raffaillac@inria.fr> wrote:
1) Declare a class variable
MyClass class>>initialize INT_PTR := FFIExternalValueHolder ofType: ?int?.
as a larger explanation, this will create an anonymous subclass to keep ?int? values, than later you can use as a type in your function call. Some people would call this obscure, but is a good way of solving this problem (I adopted it from old NB). If you want to have a named class instead an anonymous class, you can just subclass FFIExternalValueHolder:
FFIExternalValueHolder subclass: #MyIntPtr
and then implement typeDecl class method
MyIntPtr class>>typeDecl ^ ?int'
and this will work as the anonymous class
The second option is definitely what I want.
Personally my option would be to put my types in a class pool and use them, not to extend⦠but option is there so you can choose what you want :)
I am trying to expose a function returning several ints, as in SDL2>>mouseStateX: y: (excluding the possibility to return a Point). However I would rather not define my own int holder, can't we have generic holders to rely on?
I will not add for the moment that predefined types value holders⦠We would need to add one for each type we support to be consistent, and document it, and add tests. And btw⦠you do have a generic holder⦠is just that you need to refine it to what you want :) You could always use a ByteArray and took values later (some functions in Athens do it like that). The advantage of this approach (using plain ByteArrays) is that you do not need to change function signature at the cost of needing to do manually what the value holder does for you.
Hi Esteban, is this the way it should be done for Strings ? For example, old NBOpenGL had this Windows method to get the Window Title: getWindowText: hWnd buffer: lpString bufferSize: nMaxCount <primitive: #primitiveNativeCall module: #NativeBoostPlugin> ^self nbCall: #(int GetWindowTextA(HWND hWnd, char* lpString, int nMaxCount)) module: #user32 called as: getWindowText | len str | str := ByteString new: 1000. len := self getWindowText: self buffer: str bufferSize: 1000. ^ str first: len. When I just modify the ffiCall to getWindowText: hWnd buffer: lpString bufferSize: nMaxCount ^self ffiCall: #(int GetWindowTextA(HWND hWnd, char* lpString, int nMaxCount)) module: #user32 I get just an empty String. But If I call it with: | len str | str := ByteArray new: 1000. len := self getWindowText: self buffer: str bufferSize: 1000. ^ String fromByteArray: (str first: len). I get the real string text. Is this the way to go?
My advise is that you go with what you need, we can consider add predefined value holders later.
Esteban
Thibault
Hi, Just checked⦠contrary to what I believed, strings are passed by copy (not by reference, as ByteArray)⦠logical for safety but with penalty on performance... so yes, using a ByteArray is the correct way to do it. (Or an external value holder, which is a glorified way for passing a ByteArray, but this probably do not work fine for âchar*" because I didnât preview it :P) Esteban
On 13 Apr 2016, at 05:24, Nicolai Hess <nicolaihess@gmail.com> wrote:
2016-04-11 15:10 GMT+02:00 Esteban Lorenzano <estebanlm@gmail.com <mailto:estebanlm@gmail.com>>:
On 11 Apr 2016, at 06:24, Thibault Raffaillac <thibault.raffaillac@inria.fr <mailto:thibault.raffaillac@inria.fr>> wrote:
1) Declare a class variable
MyClass class>>initialize INT_PTR := FFIExternalValueHolder ofType: ?int?.
as a larger explanation, this will create an anonymous subclass to keep ?int? values, than later you can use as a type in your function call. Some people would call this obscure, but is a good way of solving this problem (I adopted it from old NB). If you want to have a named class instead an anonymous class, you can just subclass FFIExternalValueHolder:
FFIExternalValueHolder subclass: #MyIntPtr
and then implement typeDecl class method
MyIntPtr class>>typeDecl ^ ?int'
and this will work as the anonymous class
The second option is definitely what I want.
Personally my option would be to put my types in a class pool and use them, not to extend⦠but option is there so you can choose what you want :)
I am trying to expose a function returning several ints, as in SDL2>>mouseStateX: y: (excluding the possibility to return a Point). However I would rather not define my own int holder, can't we have generic holders to rely on?
I will not add for the moment that predefined types value holders⦠We would need to add one for each type we support to be consistent, and document it, and add tests. And btw⦠you do have a generic holder⦠is just that you need to refine it to what you want :) You could always use a ByteArray and took values later (some functions in Athens do it like that). The advantage of this approach (using plain ByteArrays) is that you do not need to change function signature at the cost of needing to do manually what the value holder does for you.
Hi Esteban,
is this the way it should be done for Strings ? For example, old NBOpenGL had this Windows method to get the Window Title:
getWindowText: hWnd buffer: lpString bufferSize: nMaxCount <primitive: #primitiveNativeCall module: #NativeBoostPlugin>
^self nbCall: #(int GetWindowTextA(HWND hWnd, char* lpString, int nMaxCount)) module: #user32
called as:
getWindowText | len str | str := ByteString new: 1000. len := self getWindowText: self buffer: str bufferSize: 1000. ^ str first: len.
When I just modify the ffiCall to
getWindowText: hWnd buffer: lpString bufferSize: nMaxCount
^self ffiCall: #(int GetWindowTextA(HWND hWnd, char* lpString, int nMaxCount)) module: #user32
I get just an empty String.
But If I call it with:
| len str | str := ByteArray new: 1000. len := self getWindowText: self buffer: str bufferSize: 1000. ^ String fromByteArray: (str first: len).
I get the real string text. Is this the way to go?
My advise is that you go with what you need, we can consider add predefined value holders later.
Esteban
Thibault
On Wed, Apr 13, 2016 at 8:52 AM, Esteban Lorenzano <estebanlm@gmail.com> wrote:
Hi,
Just checked⦠contrary to what I believed, strings are passed by copy (not by reference, as ByteArray)⦠logical for safety but with penalty on performance... so yes, using a ByteArray is the correct way to do it. (Or an external value holder, which is a glorified way for passing a ByteArray, but this probably do not work fine for âchar*" because I didnât preview it :P)
Hello,
I've never used UFFI before, but would like to call setxattr and getxattr in LibC on OS X (which also pass strings). I don't have a lot of Mac or Unix background, but I have past experience fiddling with parameters to call external Windows libraries from VB. Is there any general information about UFFI usage anywhere, or is reviewing this thread my best place to start? Thank you, Rob
Le 13/04/2016 15:23, Rob Rothwell a écrit :
On Wed, Apr 13, 2016 at 8:52 AM, Esteban Lorenzano <estebanlm@gmail.com <mailto:estebanlm@gmail.com>> wrote:
Hi,
Just checked⦠contrary to what I believed, strings are passed by copy (not by reference, as ByteArray)⦠logical for safety but with penalty on performance... so yes, using a ByteArray is the correct way to do it. (Or an external value holder, which is a glorified way for passing a ByteArray, but this probably do not work fine for âchar*" because I didnât preview it :P)
Hello,
I've never used UFFI before, but would like to call setxattr and getxattr in LibC on OS X (which also pass strings). I don't have a lot of Mac or Unix background, but I have past experience fiddling with parameters to call external Windows libraries from VB.
Is there any general information about UFFI usage anywhere, or is reviewing this thread my best place to start?
This is pretty new but there is some thread in the mailing list about it. Esteban also begun a documentation: https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgres...
Thank you,
Rob
-- Cyril Ferlicot http://www.synectique.eu 165 Avenue Bretagne Lille 59000 France
This is pretty new but there is some thread in the mailing list about it.
Esteban also begun a documentation:
https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgres...
Thanks Cyril, this is a very nice start and helps a lot! Take care, Rob
Le 13/04/2016 20:41, Rob Rothwell a écrit :
This is pretty new but there is some thread in the mailing list about it.
Esteban also begun a documentation: https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgres...
Thanks Cyril, this is a very nice start and helps a lot!
Take care,
Rob
There was also a presentation at Pharo Days but I think it is not on the web for now. Latter it will be available on slideshare. Or maybe Esteban will send it before :) -- Cyril Ferlicot http://www.synectique.eu 165 Avenue Bretagne Lille 59000 France
participants (5)
-
Cyril Ferlicot D. -
Esteban Lorenzano -
Nicolai Hess -
Rob Rothwell -
Thibault Raffaillac