[squeak-dev] Send NULL to a C function trough FFI

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

[squeak-dev] Send NULL to a C function trough FFI

Mariano Martinez Peck
Hi everybody!

I need to call a C function with a NULL value in one of the parameter. I tried to send it a nil but I got an error in FFI when trying to call that function. The error is: "cannot coerce arguments". Obviously this error says FFI cannot map from nil to null.

Do someone know how can I do this?

many thanks,

mariano


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Send NULL to a C function trough FFI

Igor Stasenko
2008/9/17 Mariano Martinez Peck <[hidden email]>:
> Hi everybody!
>
> I need to call a C function with a NULL value in one of the parameter. I
> tried to send it a nil but I got an error in FFI when trying to call that
> function. The error is: "cannot coerce arguments". Obviously this error says
> FFI cannot map from nil to null.
>
> Do someone know how can I do this?
>
you mean C's NULL?
AFAIK it defined as
#define NULL 0

so, in squeak you can simply pass 0.

> many thanks,
>
> mariano
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Send NULL to a C function trough FFI

Mariano Martinez Peck
Igor: I tried what you said but I get the same error. Here is more information:

The C function is like this:
 
int odbx_result(
odbx_t* handle,
odbx_result_t** result,
struct timeval* timeout,
unsigned long chunk )

My method with FFI is this:

apiQueryResult: connectionHandle handle: handle timeout: timeout chunk: chunk
    <cdecl: long 'odbx_result' (ulong ulong* DBXTimeSpec ulong) module: 'opendbx'>
    ^self externalCallFailed

And DBXTimeSpec has 2 attributes (seconds y nseconds). It has this class message:

DBXTimeSpec
fields
    ^#(
        (seconds         'long')
        (nseconds    'long'))


Many thanks,

Mariano



On Wed, Sep 17, 2008 at 2:02 AM, Igor Stasenko <[hidden email]> wrote:
2008/9/17 Mariano Martinez Peck <[hidden email]>:
> Hi everybody!
>
> I need to call a C function with a NULL value in one of the parameter. I
> tried to send it a nil but I got an error in FFI when trying to call that
> function. The error is: "cannot coerce arguments". Obviously this error says
> FFI cannot map from nil to null.
>
> Do someone know how can I do this?
>
you mean C's NULL?
AFAIK it defined as
#define NULL 0

so, in squeak you can simply pass 0.

> many thanks,
>
> mariano
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.




Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Send NULL to a C function trough FFI

Andreas.Raab
In reply to this post by Igor Stasenko
Igor Stasenko wrote:

> 2008/9/17 Mariano Martinez Peck <[hidden email]>:
>> Hi everybody!
>>
>> I need to call a C function with a NULL value in one of the parameter. I
>> tried to send it a nil but I got an error in FFI when trying to call that
>> function. The error is: "cannot coerce arguments". Obviously this error says
>> FFI cannot map from nil to null.
>>
>> Do someone know how can I do this?
>>
> you mean C's NULL?
> AFAIK it defined as
> #define NULL 0
>
> so, in squeak you can simply pass 0.

Except where pointers are expected - the FFI does not allow passing an
int as a pointer. Using nil is the correct way of doing it. If it
doesn't work then there is something wrong with the declaration.

Cheers,
   - Andreas



Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Send NULL to a C function trough FFI

Andreas.Raab
In reply to this post by Mariano Martinez Peck
Mariano Martinez Peck wrote:

> Igor: I tried what you said but I get the same error. Here is more information:
>
> The C function is like this:
>  
> int *odbx_result*(
>     odbx_t* /*handle*/,
>     odbx_result_t** /*result*/,
>
>     struct timeval* /*timeout*/,
>     unsigned long /*chunk*/ )
>
>
> My method with FFI is this:
>
> apiQueryResult: connectionHandle handle: handle timeout: timeout chunk:
> chunk
>     <cdecl: long 'odbx_result' (ulong ulong* DBXTimeSpec ulong) module:
> 'opendbx'>
>     ^self externalCallFailed

The reason it doesn't work is that the FFI spec doesn't match the C
function declaration. Both the first and third argument are declared
pointers in C, and not declared pointers in the FFI. This is
particularly problematic with the struct timeval since the FFI now
expects you to pass the struct timeval by value (since you haven't
declared it as being a pointer) and will not accept nil as argument
(since it would have to dereference the pointer and consequently crash).
Try the following declaration instead:

<cdecl: long 'odbx_result' (ulong* ulong* DBXTimeSpec* ulong) module:
'opendbx'>

This will accept nil as the parameter for the timeout value.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Send NULL to a C function trough FFI

Mariano Martinez Peck


On Wed, Sep 17, 2008 at 2:26 AM, Andreas Raab <[hidden email]> wrote:
Mariano Martinez Peck wrote:
Igor: I tried what you said but I get the same error. Here is more information:

The C function is like this:
 int *odbx_result*(
   odbx_t* /*handle*/,
   odbx_result_t** /*result*/,

   struct timeval* /*timeout*/,
   unsigned long /*chunk*/ )


My method with FFI is this:

apiQueryResult: connectionHandle handle: handle timeout: timeout chunk: chunk
   <cdecl: long 'odbx_result' (ulong ulong* DBXTimeSpec ulong) module: 'opendbx'>
   ^self externalCallFailed

The reason it doesn't work is that the FFI spec doesn't match the C function declaration. Both the first and third argument are declared pointers in C, and not declared pointers in the FFI. This is particularly problematic with the struct timeval since the FFI now expects you to pass the struct timeval by value (since you haven't declared it as being a pointer) and will not accept nil as argument (since it would have to dereference the pointer and consequently crash). Try the following declaration instead:


<cdecl: long 'odbx_result' (ulong* ulong* DBXTimeSpec* ulong) module: 'opendbx'>

This will accept nil as the parameter for the timeout value.


Andreas: You were right. It was that. I changed to DBXTimeSpec* and now I can send nil.

Many thanks,

mariano

 

Cheers,
 - Andreas