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.
On Fri, Feb 16, 2018 at 9:07 AM, Torsten Bergmann <astares@gmx.de> 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.
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 <shirofaii@gmail.com> 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 <estebanlm@gmail.com> 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) ].
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
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 <shirofaii@gmail.com> 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 17 Feb 2018, at 02:50, Ben Coman <btc@openInWorld.com> wrote:
On 16 February 2018 at 16:38, Esteban Lorenzano <estebanlm@gmail.com <mailto:estebanlm@gmail.com>> 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) ].
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.
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
cheers -ben
^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 <shirofaii@gmail.com <mailto:shirofaii@gmail.com>> 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 <http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html>
On 18 February 2018 at 01:46, Esteban Lorenzano <estebanlm@gmail.com> wrote:
On 17 Feb 2018, at 02:50, Ben Coman <btc@openInWorld.com> wrote:
On 16 February 2018 at 16:38, Esteban Lorenzano <estebanlm@gmail.com> 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) ].
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.
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?
That will be useful, and intuitive for people to find. cheers -ben
Esteban
cheers -ben
^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 <shirofaii@gmail.com> 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
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
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 <estebanlm@gmail.com> 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 <shirofaii@gmail.com> 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
participants (5)
-
Ben Coman -
Egor Scorik -
Esteban Lorenzano -
Stephane Ducasse -
Torsten Bergmann