Using Lua FFI with complex types - c

Bit of a complicated use case... Trying to access a C++ Object inside of Lua FFI, via a C wrapper.
ffi.load("wrapper.so")
​
ffi.cdef[[
struct puppy;
typedef struct puppy puppy_t;
puppy_t * puppy_bark (const char *encoded);
]]
However every time I try to instantiate a puppy, it returns "size of C type is unknown or too large".
I've tried the following to get a puppy created...
pup = ffi.typeof("puppy_t")
pup.puppy_bark("some text")
Results in struct puppy has no member named puppy_bark
pup = ffi.new("struct puppy_t")
pup.puppy_bark("some text")
Returns undeclared or implicit tag
pup = ffi.new("struct puppy puppy_t")
pup.puppy_bark("some stringish thing")
Returns '<eof>' expected near puppy_t
Assuming that the C Wrapper correctly has a Puppy Struct, Type, and the requisite method, how do create an instance of or a pointer to a Puppy in order to make it bark?
Thanks in advance!

You ask "how do I create an instance of or a pointer to a puppy in order to make it bark" - but it's not possible to create an instance of something without having its definition, and it's not possible to create a pointer to something without having an instance of it, and puppies don't bark with your code anyway (but there is a global function puppy_bark that creates a new puppy?).
It looks like you can create a puppy by calling puppy_bark (in which case, what a horribly badly named function!), but I can't be sure of that without seeing the actual code behind puppy_bark.
Since I don't have a specific answer to a specific question, here are some things that are likely to help you:
ffi.new("puppy_t") doesn't work because the FFI needs to have the definition of struct puppy, not just a forward declaration, for exactly the same reason this won't work in C++:
struct puppy;
puppy *p = new puppy;
So, if you want to do this, you need to load the complete definition into the FFI. Note that LuaJIT's FFI only supports C code, not C++.
ffi.new("struct puppy_t") doesn't work because that's not a type that exists.
ffi.new("struct puppy puppy_t") don't work because that's not a valid type.
pup = ffi.typeof("puppy_t") pup.puppy_bark("some text") doesn't work because puppy_bark isn't a member of struct puppy (as the error message tells you).
It also seems like you're misunderstanding the purpose of ffi.typeof. According to the documentation, ffi.typeof returns a constructor for the given type, so that
local new_puppy = ffi.typeof("puppy_t")
local puppy = new_puppy(1, 2, 3, 4)
is the same as
local puppy = ffi.new("puppy_t", 1, 2, 3, 4)
If you want to call the global function puppy_bark, you can do that with ffi.C.puppy_bark("some text").

Related

Accessing data from a structure returned by C function in Python using ctypes

I know the subject has already been treated, but I've failed to find anything that works for me, so I guess my problem is slightly different from the others.
What I do, basically, is that I use a C function wrapped into a python code using ctypes.
My goal is to compute some quantities in the C function, store them into a single structure, and return the structure in Python where I could read all the different data in the structure.
So :
To define my structure in python, I use :
class BITE(ctypes.Structure):
_fields_ = [
("lum", ctypes.c_int),
("suce", ctypes.c_int)
]
I compile like that :
sub.call(["gcc","-shared","-Wl,-install_name,ex.so","-o","ex.so","-fPIC","ex.c"])
lum = ctypes.CDLL('ex.so')
lum = lum.lum
I declare the arguments and result types like this :
lum.restype = ctypes.POINTER(BITE)
lum.argtypes = [ctypes.POINTER(ctypes.c_float),ctypes.c_int,ctypes.POINTER(ctypes.c_float),ctypes.c_int,ctypes.POINTER(ctypes.c_float),ctypes.POINTER(ctypes.c_float),ctypes.c_int,ctypes.POINTER(ctypes.c_float),ctypes.c_int,ctypes.POINTER(ctypes.c_float),ctypes.POINTER(ctypes.c_float),ctypes.POINTER(ctypes.c_float),ctypes.POINTER(ctypes.c_float),ctypes.c_float,ctypes.c_float,ctypes.c_float,ctypes.c_float,ctypes.c_float]
Then, I call the C function "lum" in the python code
out = lum(all the different variables needed)
The problem begins here. I have my structure, but impossible to read the data stored in each fields.
A partial solution I found is to do :
out = out[0]
But then, when doing
print(out.suce)
I have a segmentation fault 11. DOn't know why. I tried to understand how to used create_string_buffer, but I didn't really understand how it works and what it supposed to do. Moreover, I tried to using as a black box, and still, nothing works.
I also tried some other solutions mentionned in other threads such as using out.contents or something like that, but it has no .contents attributes. Nor out.suce.value, which is also something I saw somewhere during my desperate research.
Of course, I checked in the C code that the structure exists and that each field of the structure exists, and has the right data in it.
Thanks.
Suppose you have a C-structure like this :
typedef struct _servParams
{
unsigned short m_uServPort;
char m_pInetAddr[MAX_LENGTH_OF_IP_ADDRESS];
} ServerParams_t;
To use it within ctypes you should create a wrapper like this :
class ServerParams_t(Structure):
_fields_ = [ ("m_uServPort", c_ushort),
("m_pInetAddr", (c_char * 16)) ]
Later on inside your python you can use the following snippet :
servParams = ServerParams_t()
servParams.m_uServPort = c_ushort(int(port))
servParams.m_pInetAddr = ip.encode()
If you need to pass it by value, simply pass servParams variable to you api. If you need to pass a pointer use byref(servParams).

c2hs bind both typedef and function

I am trying to properly create haskell bindings for function in C, that is split up in 2 files.
file1.h: typedef const char* fmi2GetTypesPlatformTYPE(void);
file2.h: __declspec(dllexport) fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform;
To match this in Haskell I have created a similar structure, but this is where the trouble is.
file1.chs: type fmi2GetTypesPlatformTYPE = {#type fmi2GetTypesPlatformTYPE#}
How do I create a Haskell function pointer using this type? I have imported the file with {#import file1 #}, but I am lost on how to accomplish the last part.
See https://github.com/haskell/c2hs/issues/142
I will post the answer once resolved (unless Ian-ross beats me to it :) )

D-Bus how to create and send a Dict?

I have a process which exposes a method to DBus with one of the arguments taking the following type signature a{sv}:
Dict of {String, Variant}
The libDBus documentation for dbus_message_append_args fails to provide adequate reference for this. Some information appears in the specification under container-types, specifically:
A DICT_ENTRY works exactly like a struct, but rather than parentheses
it uses curly braces, and it has more restrictions. The restrictions
are: it occurs only as an array element type; it has exactly two
single complete types inside the curly braces; the first single
complete type (the "key") must be a basic type rather than a container
type. Implementations must not accept dict entries outside of arrays,
must not accept dict entries with zero, one, or more than two fields,
and must not accept dict entries with non-basic-typed keys. A dict
entry is always a key-value pair.
On attempting to append a dict I receive the following error message:
type dict_entry isn't supported yet in dbus_message_append_args_valist
Although I'm actually using dbus_message_append_args(I guess the error message is somewhat off).
There are two other alternatives to dbus_message_append_args() using either:
dbus_message_iter_append_basic()
and
dbus_message_iter_append_fixed_array()
While I can create an empty Dict container with the following:
const char * container_d_sig = "{sv}";
DBusMessageIter iter, sub;
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, container_d_sig, &sub);
dbus_message_iter_close_container(&iter, &sub);
Neither of the append methods appear to support adding a struct. Not sure what to try here...
First, about D-Bus libraries: you talk about dbus-glib in several places but the functions you refer to are not part of dbus-glib but libdbus. If you are still trying to find the best way to use D-Bus, I suggest you forget both of these: libdbus is very low-level (it's documentation even starts with "If you use this low-level API directly, you're signing up for some pain") and dbus-glib is deprecated. The best D-Bus API currently is GDBus which is part of GLib GIO: it's a far better designed API than either of the other two, well tested and supported.
Now, as for the actual question, documentation for dbus_message_append_args() does say it quite clearly:
To append variable-length basic types, or any more complex value, you
have to use an iterator rather than this function.
In other words you should use dbus_message_iter_open_container() to prepare the iterator until it is pointing to somewhere where you can use dbus_message_iter_append_basic(). Note that in your example the dictionary is a container, the dictionary entry is a container and the variant is a container... In other words it gets pretty complex quite fast. If you really want to do it, look at e.g. Connman code for examples.
As I mentioned, the sane route is GDBus. There creating even much more complex signatures is pretty easy as you can use the GVariantBuilder API:
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "name1", my_variant);
/* Now use the builder results with g_dbus_connection_call()
or g_dbus_proxy_call() */
I know this question was asked awhile ago, but I had a very similar question recently, and after several hours of trial and error this is some code I came up with that works for me. Hopefully it helps someone else...
DBusMessage* testMessage()
{
DBusMessage* mssg = dbus_message_new_signal("/fi/w1/wpa_supplicant1/Interfaces/0", "fi.w1.wpa_supplicant1.Interface", "PropertiesChanged");
DBusMessageIter iter, aIter;
dbus_message_iter_init_append(mssg, &iter);
if (!dbus_message_iter_open_container(&iter, 'a', "{sv}", &aIter))
return nullptr;
DBusMessageIter eIter;
if (!dbus_message_iter_open_container(&aIter, 'e', NULL, &eIter)) {
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
const char* key = "test key";
dbus_message_iter_append_basic(&eIter, 's', static_cast<void*>(&key));
DBusMessageIter vIter;
if (!dbus_message_iter_open_container(&eIter, 'v', "i", &vIter)) {
dbus_message_iter_abandon_container_if_open(&aIter, &eIter);
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
dbus_int32_t val = 42;
dbus_message_iter_append_basic(&vIter, 'i', static_cast<void*>(&val));
dbus_message_iter_close_container(&eIter, &vIter);
dbus_message_iter_close_container(&aIter, &eIter);
dbus_message_iter_close_container(&iter, &aIter);
return mssg;
}
This is C++ but should be pretty easy to adapt for C. The returned message has a signature of a{sv}. The dbus docs are helpful-ish.

SWIG R wrapper not setting class properly/Create R object from C memory pointer

I have a SWIG generated R wrapper which contains the following setClass operations:
setClass('_p_f_p_struct_parameters_p_struct_chromosome_p_struct_dataSet__double',
prototype = list(parameterTypes = c('_p_parameters', '_p_chromosome', '_p_dataSet'),
returnType = '_p_f_p_struct_parameters_p_struct_chromosome_p_struct_dataSet__double'),
contains = 'CRoutinePointer')
setClass('_p_f_p_struct_parameters_p_p_struct_chromosome_p_p_struct_chromosome_int_int__void',
prototype = list(parameterTypes = c('_p_parameters', '_p_p_chromosome', '_p_p_chromosome', '_int', '_int'),
returnType = '_p_f_p_struct_parameters_p_p_struct_chromosome_p_p_struct_chromosome_int_int__void'),
contains = 'CRoutinePointer')
These operation do not appear to be behaving as expected. When I call a function with the output being the creation of a _p_parameters object (defined above), I get the following error:
Error in getClass(Class, where = topenv(parent.frame())) :
“_p_parameters” is not a defined class
The setClass therefore seems to be not doing it's thing.
I tried to manually set the _p_parameters class via:
p_parameters<-setClass(Class="_p_parameters", representation = representation(ref = "externalptr"))
But this does not seem to work as when I try and modify other parameters (or even print parameters via an inbuilt function) the terminal crashes and hangs.
For reference, the final lines in initialiseParameters (the function which initially own _p_parameters) are calling the native C function via .Call then assigning the external pointer to a new object of class _p_paramters as follows:
;ans = .Call('R_swig_initialiseParameters', numInputs, numNodes, numOutputs, arity, as.logical(.copy), PACKAGE='cgp');
ans <- new("_p_parameters", ref=ans) ;
I've read various R doc on new(), setClass, S3/S4 classes but nothing seems to clarify what I'm meant to be doing here.
Any suggestions on where to start or tutorials that would give a good heads up would be most welcome.
Please keep in mind the C code is not mine (but is freely available under GNU), I am not a C programmer and am only weakly-moderately proficient in R. So please be gentle :)
Cheers.
PS: If I call the function in R terminal via .Call it works as expected (so it doesn't seem to e a C function error)
I thought I should post the solution I have to this. The least I could do for a 'tumbleweed' medal haha.
The only solution I could find to this is to comment out the following line:
ans <- new("_p_parameters", ref=ans) ;
in all function that try to create an R object.
The resulting memory pointer is then assigned to an R object at function call.
It's dirty, but I couldn't work out how to create an object from a memory pointer (at least from within the functions themselves).
It seems to work so I guess it will do.

Never defined structure

Is there any benefit in having never-defined structures in C ?
Example in SQLite source code :
/* struct sqlite3_stmt is never defined */
typedef struct sqlite3_stmt sqlite3_stmt;
And the object is manipulated like so :
typedef struct Vdbe Vdbe;
struct Vdbe {
/* lots of members */
};
int sqlite3_step(sqlite3_stmt *pStmt) {
Vdbe *v = (Vdbe*) pStmt;
/* do stuff with v... */
}
So why not just use a usual abstract type, with the actual structure privately defined in foo.c source and a public typedef in foo.h header ?
It is defined like this to hide the implementation detail of sqlite3_stmt from the user, thus avoiding the internal states from being messed around. See Opaque pointer.
(This also forces the user only to use the type as a pointer since the structure sqlite3_stmt itself has incomplete implementation.)
Edit: VDBE (virtual database engine) is just "a" back-end of the SQLite3 API. I believe the back-end is changeable, thus a sqlite3_stmt* is not necessarily a Vdbe*. Not exposing Vdbe* in the API because the back-end detail should not be exposed.
To clarify: What you're asking is why SQLite does the above instead of doing this:
Header file:
typedef struct sqlite3_stmt sqlite3_stmt;
C file:
struct sqlite3_stmt {
/* lots of members */
};
int sqlite3_step(sqlite3_stmt *pStmt) {
/* do stuff with pStmt... */
}
(This is the canonical form of the "opaque pointer" pattern linked to in KennyTM's answer.)
The only good reason I can think of why SQLite does what it does is the following:
The backend code, I'm speculating, came before the API and used the name Vdbe -- the name probably means something related to the implementation along the lines of "virtual database entry" (guessing wildly here).
When time came to create the API, someone realized that the parameter required by sqlite3_step was a Vdbe but that this was not exactly a name that would convey a lot to the user of the API. Hence, from the user's point of view, a Vdbe is referred to as an sqlite3_stmt.
The point here, then, is to differentiate between two views of the same item: The backend thinks in terms of Vdbes (whatever they are) because that's a name that makes sense in the context of the implementation. The API talks about sqlite3_stmts because that's a name that makes sense in the context of the interface.
Edit: As Amarghosh points out, why not just do this to achieve the same effect?
typedef struct Vdbe sqlite3_stmt;
KennyTM points out a good possible reason (please vote him up, I don't want to siphon off his rep here): VDBE is only one of several possible backends; the interface uses a "generic" sqlite3_stmt, and this is then cast to whatever the backend uses to implement it.

Resources