UFFI const, unsigned, opaque-ish types

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

UFFI const, unsigned, opaque-ish types

Ben Coman
For this definition pulled from a library header file...
    typedef struct {
        const void *data;
        unsigned private_flags;
    } CXString;

which is used with a helper function to get a usable string like...
  void show_clang_version(void)
  {    CXString version = clang_getClangVersion();
       printf("%s\n", clang_getCString(version));
       clang_disposeString(version);
  }

==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on
LLVM 3.5.0)'


So I defined...
    FFIExternalStructure subclass: #CXString
        instanceVariableNames: ''
        classVariableNames: ''
        package: 'LibCLang'

and ignoring the const as advised in the manual [1],  I try...
    CXString class >> fieldsDesc
    ^ #(
         void *data;
         unsigned private_flags;
         )

but...
    CXString rebuildFieldAccessors.
    ==>Error: Unable to resolve external type: unsigned

I also tried  "unsigned int private_flags;"
but get the same error. Any ideas what is wrong?


Actually I can kind of ignore creating accessors since this is like an
opaque type where I'm not expected to access its internals, but I do
need CXString as a return value like this...

  LibCLang class >> getClangVersion
     ^ self ffiCall: #( CXString clang_getClangVersion () ) module: LibCLang

which needs to be passed to this function to get a workable string....

  LibCLang class >> getString: aCXString
     ^ self ffiCall: #( String clang_getCString ( CXString aCXString )
) module: LibCLang

However this doesn't work if I use FFIOpaqueObject instead of
FFIExternalStructure.
I guess the difference is opaque objects are normally pointers to a
type, whereas here that pointer is contained in a struct.

What I've done at the moment to push ahead with experimenting is avoid
needing to generate accessors by adding...

   CXString >> printOn: asStream
        self getString printOn: aStream

    CXString >> getString
        ^ self ffiCall: #( String clang_getCString ( CXString self ) )
module: LibCLang

such that...
   LibCLang getClangVersion "<Print It>"
   ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based
on LLVM 3.5.0)'


Is there a better way to approach this?

cheers -ben

btw, this is in Pharo 5 (Moose 6).

[1] https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/UnifiedFFI/UnifiedFFI.pdf

Reply | Threaded
Open this post in threaded view
|

Re: UFFI const, unsigned, opaque-ish types

EstebanLM
Hi,

(Short because I'm by phone)

Const should be ignored so you can keep it (if not is a bug)
Unsigned does not exist :)
You can always put an alias, but the type you are looking for is "uint"

Cheers,
Esteban

> On 31 Aug 2016, at 18:59, Ben Coman <[hidden email]> wrote:
>
> For this definition pulled from a library header file...
>    typedef struct {
>        const void *data;
>        unsigned private_flags;
>    } CXString;
>
> which is used with a helper function to get a usable string like...
>  void show_clang_version(void)
>  {    CXString version = clang_getClangVersion();
>       printf("%s\n", clang_getCString(version));
>       clang_disposeString(version);
>  }
>
> ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on
> LLVM 3.5.0)'
>
>
> So I defined...
>    FFIExternalStructure subclass: #CXString
>        instanceVariableNames: ''
>        classVariableNames: ''
>        package: 'LibCLang'
>
> and ignoring the const as advised in the manual [1],  I try...
>    CXString class >> fieldsDesc
>    ^ #(
>         void *data;
>         unsigned private_flags;
>         )
>
> but...
>    CXString rebuildFieldAccessors.
>    ==>Error: Unable to resolve external type: unsigned
>
> I also tried  "unsigned int private_flags;"
> but get the same error. Any ideas what is wrong?
>
>
> Actually I can kind of ignore creating accessors since this is like an
> opaque type where I'm not expected to access its internals, but I do
> need CXString as a return value like this...
>
>  LibCLang class >> getClangVersion
>     ^ self ffiCall: #( CXString clang_getClangVersion () ) module: LibCLang
>
> which needs to be passed to this function to get a workable string....
>
>  LibCLang class >> getString: aCXString
>     ^ self ffiCall: #( String clang_getCString ( CXString aCXString )
> ) module: LibCLang
>
> However this doesn't work if I use FFIOpaqueObject instead of
> FFIExternalStructure.
> I guess the difference is opaque objects are normally pointers to a
> type, whereas here that pointer is contained in a struct.
>
> What I've done at the moment to push ahead with experimenting is avoid
> needing to generate accessors by adding...
>
>   CXString >> printOn: asStream
>        self getString printOn: aStream
>
>    CXString >> getString
>        ^ self ffiCall: #( String clang_getCString ( CXString self ) )
> module: LibCLang
>
> such that...
>   LibCLang getClangVersion "<Print It>"
>   ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based
> on LLVM 3.5.0)'
>
>
> Is there a better way to approach this?
>
> cheers -ben
>
> btw, this is in Pharo 5 (Moose 6).
>
> [1] https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/UnifiedFFI/UnifiedFFI.pdf
>

Reply | Threaded
Open this post in threaded view
|

Re: UFFI const, unsigned, opaque-ish types

Ben Coman
Thanks Esteban. That worked.

However it may be good to be more permissive about allowing const to
reduce the surprises for FFI users.  Same for unsigned.

Reviewing   FFIExternalStructureFIeldParser>>praseFields:structure:
I see declarations are parsed simply left-to-right, which okay as the
simplest-thing-that-would-work.   However (in case I get inspired...),
would this benefit from more complex parsing like described at [1] and
[2]?  Or is this unlikely to be a concern in prcatice, and/or the rest
of FFI not ready receive such complex declarations from the parser?

[1] http://www.geeksforgeeks.org/complicated-declarations-in-c/
[2] http://unixwiz.net/techtips/reading-cdecl.html

cheers -ben

On Thu, Sep 1, 2016 at 2:01 AM, Esteban Lorenzano <[hidden email]> wrote:

> Hi,
>
> (Short because I'm by phone)
>
> Const should be ignored so you can keep it (if not is a bug)
> Unsigned does not exist :)
> You can always put an alias, but the type you are looking for is "uint"
>
> Cheers,
> Esteban
>
>> On 31 Aug 2016, at 18:59, Ben Coman <[hidden email]> wrote:
>>
>> For this definition pulled from a library header file...
>>    typedef struct {
>>        const void *data;
>>        unsigned private_flags;
>>    } CXString;
>>
>> which is used with a helper function to get a usable string like...
>>  void show_clang_version(void)
>>  {    CXString version = clang_getClangVersion();
>>       printf("%s\n", clang_getCString(version));
>>       clang_disposeString(version);
>>  }
>>
>> ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on
>> LLVM 3.5.0)'
>>
>>
>> So I defined...
>>    FFIExternalStructure subclass: #CXString
>>        instanceVariableNames: ''
>>        classVariableNames: ''
>>        package: 'LibCLang'
>>
>> and ignoring the const as advised in the manual [1],  I try...
>>    CXString class >> fieldsDesc
>>    ^ #(
>>         void *data;
>>         unsigned private_flags;
>>         )
>>
>> but...
>>    CXString rebuildFieldAccessors.
>>    ==>Error: Unable to resolve external type: unsigned
>>
>> I also tried  "unsigned int private_flags;"
>> but get the same error. Any ideas what is wrong?
>>
>>
>> Actually I can kind of ignore creating accessors since this is like an
>> opaque type where I'm not expected to access its internals, but I do
>> need CXString as a return value like this...
>>
>>  LibCLang class >> getClangVersion
>>     ^ self ffiCall: #( CXString clang_getClangVersion () ) module: LibCLang
>>
>> which needs to be passed to this function to get a workable string....
>>
>>  LibCLang class >> getString: aCXString
>>     ^ self ffiCall: #( String clang_getCString ( CXString aCXString )
>> ) module: LibCLang
>>
>> However this doesn't work if I use FFIOpaqueObject instead of
>> FFIExternalStructure.
>> I guess the difference is opaque objects are normally pointers to a
>> type, whereas here that pointer is contained in a struct.
>>
>> What I've done at the moment to push ahead with experimenting is avoid
>> needing to generate accessors by adding...
>>
>>   CXString >> printOn: asStream
>>        self getString printOn: aStream
>>
>>    CXString >> getString
>>        ^ self ffiCall: #( String clang_getCString ( CXString self ) )
>> module: LibCLang
>>
>> such that...
>>   LibCLang getClangVersion "<Print It>"
>>   ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based
>> on LLVM 3.5.0)'
>>
>>
>> Is there a better way to approach this?
>>
>> cheers -ben
>>
>> btw, this is in Pharo 5 (Moose 6).
>>
>> [1] https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/UnifiedFFI/UnifiedFFI.pdf
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: UFFI const, unsigned, opaque-ish types

EstebanLM
well, I accept contributions :)
I was thinking about enhance the parser too (but for allowing array declarations, not for unsigned)…
 anyway, as soon as tests passes and backward compatibility is there, I would like to have a better parser, yes.

cheers,
Esteban

> On 01 Sep 2016, at 18:40, Ben Coman <[hidden email]> wrote:
>
> Thanks Esteban. That worked.
>
> However it may be good to be more permissive about allowing const to
> reduce the surprises for FFI users.  Same for unsigned.
>
> Reviewing   FFIExternalStructureFIeldParser>>praseFields:structure:
> I see declarations are parsed simply left-to-right, which okay as the
> simplest-thing-that-would-work.   However (in case I get inspired...),
> would this benefit from more complex parsing like described at [1] and
> [2]?  Or is this unlikely to be a concern in prcatice, and/or the rest
> of FFI not ready receive such complex declarations from the parser?
>
> [1] http://www.geeksforgeeks.org/complicated-declarations-in-c/
> [2] http://unixwiz.net/techtips/reading-cdecl.html
>
> cheers -ben
>
> On Thu, Sep 1, 2016 at 2:01 AM, Esteban Lorenzano <[hidden email]> wrote:
>> Hi,
>>
>> (Short because I'm by phone)
>>
>> Const should be ignored so you can keep it (if not is a bug)
>> Unsigned does not exist :)
>> You can always put an alias, but the type you are looking for is "uint"
>>
>> Cheers,
>> Esteban
>>
>>> On 31 Aug 2016, at 18:59, Ben Coman <[hidden email]> wrote:
>>>
>>> For this definition pulled from a library header file...
>>>   typedef struct {
>>>       const void *data;
>>>       unsigned private_flags;
>>>   } CXString;
>>>
>>> which is used with a helper function to get a usable string like...
>>> void show_clang_version(void)
>>> {    CXString version = clang_getClangVersion();
>>>      printf("%s\n", clang_getCString(version));
>>>      clang_disposeString(version);
>>> }
>>>
>>> ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on
>>> LLVM 3.5.0)'
>>>
>>>
>>> So I defined...
>>>   FFIExternalStructure subclass: #CXString
>>>       instanceVariableNames: ''
>>>       classVariableNames: ''
>>>       package: 'LibCLang'
>>>
>>> and ignoring the const as advised in the manual [1],  I try...
>>>   CXString class >> fieldsDesc
>>>   ^ #(
>>>        void *data;
>>>        unsigned private_flags;
>>>        )
>>>
>>> but...
>>>   CXString rebuildFieldAccessors.
>>>   ==>Error: Unable to resolve external type: unsigned
>>>
>>> I also tried  "unsigned int private_flags;"
>>> but get the same error. Any ideas what is wrong?
>>>
>>>
>>> Actually I can kind of ignore creating accessors since this is like an
>>> opaque type where I'm not expected to access its internals, but I do
>>> need CXString as a return value like this...
>>>
>>> LibCLang class >> getClangVersion
>>>    ^ self ffiCall: #( CXString clang_getClangVersion () ) module: LibCLang
>>>
>>> which needs to be passed to this function to get a workable string....
>>>
>>> LibCLang class >> getString: aCXString
>>>    ^ self ffiCall: #( String clang_getCString ( CXString aCXString )
>>> ) module: LibCLang
>>>
>>> However this doesn't work if I use FFIOpaqueObject instead of
>>> FFIExternalStructure.
>>> I guess the difference is opaque objects are normally pointers to a
>>> type, whereas here that pointer is contained in a struct.
>>>
>>> What I've done at the moment to push ahead with experimenting is avoid
>>> needing to generate accessors by adding...
>>>
>>>  CXString >> printOn: asStream
>>>       self getString printOn: aStream
>>>
>>>   CXString >> getString
>>>       ^ self ffiCall: #( String clang_getCString ( CXString self ) )
>>> module: LibCLang
>>>
>>> such that...
>>>  LibCLang getClangVersion "<Print It>"
>>>  ==> 'Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based
>>> on LLVM 3.5.0)'
>>>
>>>
>>> Is there a better way to approach this?
>>>
>>> cheers -ben
>>>
>>> btw, this is in Pharo 5 (Moose 6).
>>>
>>> [1] https://ci.inria.fr/pharo-contribution/view/Books/job/PharoBookWorkInProgress/lastSuccessfulBuild/artifact/book-result/UnifiedFFI/UnifiedFFI.pdf
>>>
>>
>