jmckaskill / luaffi

Standalone FFI library for calling C functions from lua. Compatible with the luajit FFI interface.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

unable to convert argument ...

daurnimator opened this issue · comments

I'm having trouble reducing to a small test case, but things work fine under luajit.

When running the code:

local mask = ffi.new ( "sigset_t[1]" )
ffi.C.sigemptyset ( mask )

I get the error: unable to convert argument 1 from cdata<struct 61[1]> to cdata<struct 26*>

sigemptyset is declared via:

typedef struct
  {
    unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
  } __sigset_t;
extern int sigemptyset (sigset_t *__set) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));

though the trailing attributes don't seem to matter

 sigset_t != __sigset_t

Except when it is :p
Sorry, I missed typedef __sigset_t sigset_t; in the paste before.
And the code still has the same error if I change my ffi.new invocation to use __sigset_t

OK so the following works for me with lua 5.2 on OSX.

typedef struct
  {
    unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
  } __sigset_t;
typedef __sigset_t sigset_t;
extern int sigemptyset (sigset_t *__set) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));

So the question is why does it not work for you...
Can you copy the output of:

require 'pretty' -- this is just a table pretty printer I included in the src
print(table.show(ffi.debug()))  -- This dumps the symbol, type table, etc.

After the cdef call.

Okay....
Btw, I warned you I was having trouble cutting the test case down :P

(damn, github cut off the file..... can I email it to you? what addr?)

in ffi.debug().functions

      ["sigemptyset"] = "ctype<int (*)(struct 24*)> 0x2266128" {
         ["env"] = {}; -- __unnamed__["functions"]["sigpending"]["env"] (self reference)
         ["mt"] = {}; -- __unnamed__["functions"]["rewind"]["env"][1]["env"][1]["mt"] (self reference)
      };

      ["sigpending"] = "ctype<int (*)(struct 24*)> 0x2268ad8" {
         ["env"] = {
            [1] = "ctype<struct 24*> 0x2265f18" {
               ["env"] = {}; -- __unnamed__["functions"]["__sigdelset"]["env"][1]["env"] (self reference)
               ["mt"] = {}; -- __unnamed__["functions"]["rewind"]["env"][1]["env"][1]["mt"] (self reference)
            };
            [0] = "ctype<int> 0x2265f98" {
               ["env"] = {}; -- __unnamed__["functions"]["rewind"]["env"][1]["env"][1]["env"] (self reference)
               ["mt"] = {}; -- __unnamed__["functions"]["rewind"]["env"][1]["env"][1]["mt"] (self reference)
            };
            ["userdata: 0x7f08f4e13c6c"] = "int (*";
            ["userdata: 0x7f08f4e13c70"] = ")(struct 24*)";
            ["userdata: 0x7f08f4e13c68"] = "int (*)(struct 24*)";
         };
         ["mt"] = {}; -- __unnamed__["functions"]["rewind"]["env"][1]["env"][1]["mt"] (self reference)
      };

in ffi.debug().types

      ["__sigset_t"] = "ctype<struct 59> 0x222ad58" {
         ["env"] = {}; -- __unnamed__["functions"]["epoll_pwait"]["env"][5]["env"] (self reference)
         ["mt"] = {}; -- __unnamed__["functions"]["rewind"]["env"][1]["env"][1]["mt"] (self reference)
      };

So it is indeed getting confused. I wonder if its getting confused with the first reference being circular.
Can you perchance email me the full ffi.cdef content and/or include it here?

OK so first off there is two typedef struct {...} __sigset_t (line 99 and 1109), which is illegal C. The parser should be erroring on that.

Otherwise this is a case of types (including function types) created between the first and second __sigset_t typedef use the first definition, but later types and your use of ffi.new use the second definition.

For now get rid of the double definitions. The bug in luaffi is to then error on the second definition.

Ah okay; I hadn't noticed I had duplicate declarations.

somehow luajit didn't seem to choke: maybe because they were identical declarations?
Are you able to copy that behaviour?

Thanks :)

I'm very loathe to allowing duplicate definitions. Strictly speaking duplicates aren't allowed by the FFI API, it's just luajit has a implementation detail at the moment where it doesn't error, but that doesn't preclude it from erring in the future. From the FFI semantics page:

Also, this is not a validating C parser. It expects and accepts correctly formed C declarations, but it may choose to ignore bad declarations or show rather generic error messages. If in doubt, please check the input against your favorite C compiler.