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 <[email protected]> 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
> 


Reply via email to