I wanted to writing bindings for libclang (so that I can generate bindings from C/C++ header files automatically), but I discovered that libclang API uses structs passed and returned by value.
typedef struct {
unsigned int_data[4];
void *ptr_data;
} CXToken;
typedef struct {
const void *data;
unsigned private_flags;
} CXString;
CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken);
So I can't really bind to this API. There are some interesting design problems to resolve: e.g. when a structure is returned by value who manages the memory of that struct and how do we prevent people from making a mistake of passing address of that struct to some other method.
/cc @sjindel-google @dcharkes I think this should probably be part of MVP - but I could not find an issue for this.
You could bind to the API btw, with some very simple C wrappers.
Why did we move this back to Flutter MVP?
We'll do the api change in MVP #37229, but not the by-value-passing.
I noticed something strange
I created a header like this
struct Data
{
int i;
};
void printData(struct Data);
struct Data createData(int);
But If I write bindings like this (using Pointer instead of passing struct by value)
typedef printData_func = ffi.Void Function(ffi.Pointer<Data>);
typedef PrintData = void Function(ffi.Pointer<Data>);
typedef create_struct_func = ffi.Pointer<Data> Function(ffi.Int32);
typedef CreateStruct = ffi.Pointer<Data> Function(int);
// we can even simply use ffi.Pointer instead of ffi.Pointer<Data>
The bindings are working perfectly (tested on ubuntu 19)
We just can't do ptr.ref to access the Struct.
Complete code can be found here
Can someone shed some light into this? (is it safe to do so), and
If there are any potential memory leak issues involved?
The Data struct with a single int field is treated as a single int field in the Linux ABI.
You're storing the _value_ of the int field as the address of the Pointer, most likely ptr.address will give you the value of the int field.
This will not work for structs that are larger than the architecture size (larger than 8 bytes on 64 bit architectures), and this will not work for structs containing floats.
Most helpful comment
The
Datastruct with a singleintfield is treated as a singleintfield in the Linux ABI.You're storing the _value_ of the int field as the address of the
Pointer, most likelyptr.addresswill give you the value of the int field.This will not work for structs that are larger than the architecture size (larger than 8 bytes on 64 bit architectures), and this will not work for structs containing floats.