Hi,
I'm trying to play with new UFFI system. It looks much easier then NativeBoost, but unfortunately its hard to find any docs or examples. I have problem with casting void* (ExternalAddress) into smalltalk object if there is no hardcoded type in ffi method. And I really dislike the idea of making many ffi methods, one for each required type. In this example i can't understand how to make something like `address castTo: type` FFIExternalObject subclass: #Iterator Iterator >> asCollectionOfType: aTypeName | result address type | result := OrderedCollection new. address := ExternalAddress new. type := FFIExternalType resolveType: aTypeName. [self iterator_next: address] whileTrue: [ result add: (address castTo: type). ]. ^result Iterator >> iterator_next: data ^ self ffiCall: #(Boolean iterator_next (Iterator self, void** data)) -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html |
>but unfortunately its hard to find any docs or examples.
PDF Docu: https://github.com/SquareBracketAssociates/Booklet-uFFI (this should be added to http://books.pharo.org) Examples: load OSWindows, OSLinuxUbuntu, ... or GlorpSQlite from catalog They all use UFFI. |
In reply to this post by Egor Scorik
hi,
“casting” is not necessary in general since is just a way to tell the C compiler that a pointer is form a certain type (but is always a pointer, and in machine code is always the same). So, here you will do something like this: Iterator >> asCollectionOfType: aTypeName | result address typeClass | result := OrderedCollection new. address := ExternalAddress new. typeClass := FFIExternalType resolveType: aTypeName. [self iterator_next: address] whileTrue: [ result add: (typeClass fromHandle: address) ]. ^result Iterator >> iterator_next: data ^ self ffiCall: #(Boolean iterator_next (Iterator self, void** data)) now… you have a problem if your type if your type is an “atomic” type, like int, long, etc. because those values are passed “by value” and not by pointer, so you will need to decode them. in this case, I would implement a method extension (probably it worths to add it to UFFI): FFIExternalType class >> valueFromHandle: anAddress ^ self new handle: anAddress at: 1 “This is used for structures, but we can reuse them :)" FFIExternalReference class >> valueFromHandle: anAddress ^ self fromHandle: anAddress FFIExternalStructure class >> valueFromHandle: anAddress ^ self fromHandle: anAddress So your function will be like something like this: Iterator >> asCollectionOfType: aTypeName | result address typeClass | result := OrderedCollection new. address := ExternalAddress new. typeClass := FFIExternalType resolveType: aTypeName. [self iterator_next: address] whileTrue: [ result add: (typeClass valueFromHandle:: address) ]. ^result and voilà, you have your cast :) Esteban ps: (some errors can be found here, since I’m “programming at mail client”, but you get the idea ;) ) > On 15 Feb 2018, at 19:59, Egor Scorik <[hidden email]> wrote: > > Hi, > > I'm trying to play with new UFFI system. It looks much easier then > NativeBoost, but unfortunately its hard to find any docs or examples. > I have problem with casting void* (ExternalAddress) into smalltalk object if > there is no hardcoded type in ffi method. And I really dislike the idea of > making many ffi methods, one for each required type. > In this example i can't understand how to make something like `address > castTo: type` > > FFIExternalObject subclass: #Iterator > > Iterator >> asCollectionOfType: aTypeName > | result address type | > > result := OrderedCollection new. > address := ExternalAddress new. > type := FFIExternalType resolveType: aTypeName. > [self iterator_next: address] whileTrue: [ > result add: (address castTo: type). > ]. > ^result > > Iterator >> iterator_next: data > ^ self ffiCall: #(Boolean iterator_next (Iterator self, void** data)) > > > > > -- > Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html > |
On 16 February 2018 at 16:38, Esteban Lorenzano <[hidden email]> wrote: hi, Perhaps this is a bit about discover-ability. People with C experience may naturally search for "cast". If I Spotter search for..... cast #i it turns up only four... "broadcast" under Socket class If that was instead like... (typeClass castFromHandle: address) then people may be more likely to find it themselves. cheers -ben ^result |
In reply to this post by Torsten Bergmann
On Fri, Feb 16, 2018 at 9:07 AM, Torsten Bergmann <[hidden email]> wrote:
>>but unfortunately its hard to find any docs or examples. > > PDF Docu: https://github.com/SquareBracketAssociates/Booklet-uFFI > > (this should be added to http://books.pharo.org) It will be added when it will be completed. And since this is not me that will do it because I cannot then I wait. May be one day someone with enough knowledge will consider that FFI is important enough to document it seriously. Stef > > Examples: load OSWindows, OSLinuxUbuntu, ... or GlorpSQlite from catalog > They all use UFFI. > |
In reply to this post by EstebanLM
Hi esteban
do you plan to add this explanation to the documentation of uFFI? Stef On Fri, Feb 16, 2018 at 9:38 AM, Esteban Lorenzano <[hidden email]> wrote: > hi, > > “casting” is not necessary in general since is just a way to tell the C compiler that a pointer is form a certain type (but is always a pointer, and in machine code is always the same). > > So, here you will do something like this: > > Iterator >> asCollectionOfType: aTypeName > | result address typeClass | > > result := OrderedCollection new. > address := ExternalAddress new. > typeClass := FFIExternalType resolveType: aTypeName. > [self iterator_next: address] > whileTrue: [ result add: (typeClass fromHandle: address) ]. > ^result > > Iterator >> iterator_next: data > ^ self ffiCall: #(Boolean iterator_next (Iterator self, void** data)) > > now… you have a problem if your type if your type is an “atomic” type, like int, long, etc. because those values are passed “by value” and not by pointer, so you will need to decode them. > in this case, I would implement a method extension (probably it worths to add it to UFFI): > > FFIExternalType class >> valueFromHandle: anAddress > ^ self new handle: anAddress at: 1 “This is used for structures, but we can reuse them :)" > > FFIExternalReference class >> valueFromHandle: anAddress > ^ self fromHandle: anAddress > > FFIExternalStructure class >> valueFromHandle: anAddress > ^ self fromHandle: anAddress > > So your function will be like something like this: > > Iterator >> asCollectionOfType: aTypeName > | result address typeClass | > > result := OrderedCollection new. > address := ExternalAddress new. > typeClass := FFIExternalType resolveType: aTypeName. > [self iterator_next: address] > whileTrue: [ result add: (typeClass valueFromHandle:: address) ]. > ^result > > and voilà, you have your cast :) > > Esteban > > ps: (some errors can be found here, since I’m “programming at mail client”, but you get the idea ;) ) > >> On 15 Feb 2018, at 19:59, Egor Scorik <[hidden email]> wrote: >> >> Hi, >> >> I'm trying to play with new UFFI system. It looks much easier then >> NativeBoost, but unfortunately its hard to find any docs or examples. >> I have problem with casting void* (ExternalAddress) into smalltalk object if >> there is no hardcoded type in ffi method. And I really dislike the idea of >> making many ffi methods, one for each required type. >> In this example i can't understand how to make something like `address >> castTo: type` >> >> FFIExternalObject subclass: #Iterator >> >> Iterator >> asCollectionOfType: aTypeName >> | result address type | >> >> result := OrderedCollection new. >> address := ExternalAddress new. >> type := FFIExternalType resolveType: aTypeName. >> [self iterator_next: address] whileTrue: [ >> result add: (address castTo: type). >> ]. >> ^result >> >> Iterator >> iterator_next: data >> ^ self ffiCall: #(Boolean iterator_next (Iterator self, void** data)) >> >> >> >> >> -- >> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html >> > > |
In reply to this post by Ben Coman
I was thinking to implement the #castTo: for all the “pointer” classes (ByteArray, FFIExternalReference, FFIExternalStructure). #[42 0 0 0] castTo: FFIInt32 -> 42 what do you think? Esteban
|
In reply to this post by Ben Coman
Thanks! #valueFromHandle: exactly what I looking for! I also add method for
strings to make them working FFIExternalString >> valueFromHandle: anAddress | data | data := ExternalData fromHandle: anAddress type: ExternalType string. data isNull ifTrue: [ ^ nil ]. ^ data fromCString -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html |
In reply to this post by EstebanLM
On 18 February 2018 at 01:46, Esteban Lorenzano <[hidden email]> wrote:
That will be useful, and intuitive for people to find. cheers -ben
|
Free forum by Nabble | Edit this page |