ffi / ffi-swig-generator Goto Github PK
View Code? Open in Web Editor NEWTool that generates FFI bindings from swig files
Tool that generates FFI bindings from swig files
A function which takes or returns a structure by value has to be generated as follows:
typedef struct {
int i;
float f;
} foo_t;
foo_t bar(foo_t f);
class Foo < FFI::Struct
layout :i, :int
:f, :float
end
attach_function :bar, [Foo.by_value], Foo.by_value
If I use %rename() in a Swig .i file, the resultant XML has the new identifiers in the sym_name attributes (and the original names in the name attributes). But ffi-swig-generator keeps the original names, despite the fact that FFI's attach_function() can take an alternative name.
A one-line change to lib/generator/function.rb can fix this:
diff --git a/lib/generator/function.rb b/lib/generator/function.rb
index 8a26dd2..1483485 100644
--- a/lib/generator/function.rb
+++ b/lib/generator/function.rb
@@ -21,7 +21,7 @@ module FFI
params = get_params(@node).inject([]) do |array, node|
array << Argument.new(:node => node, :typedefs => @typedefs).to_s
end
- @indent_str + "attach_function :#{@symname}, [ #{params.join(', ')} ], #{get_rtype}"
+ @indent_str + "attach_function :#{get_attr('sym_name')}, :#{@symname}, [ #{params.join(', ')} ], #{get_rtype}"
end
private
def get_params(node)
If my header file has this:
#define FOO "foo"
Then the generated ruby file has this:
FOO = foo
In other words, foo is not quoted.
I think that adding the following to the case statement in the sanitize! method in Constant will address this (though not certain about nested quotes)
when 'p.char'
result = "\"#{@value}\""
When generating ruby for the following code:
enum test_enum { FIRST, SECOND, THIRD };
struct test_struct {
enum test_enum test_value;
}
ffi-gen
outputs the following ffi struct:
class TestStruct < FFI::Struct
layout(
:test_enum, :int,
)
end
It should generate the following struct instead:
class TestStruct < FFI::Struct
layout(
:test_enum, TestStruct,
)
end
Not sure how this can be handled, but basically this function
void fn(const char *fmt, va_list vl);
swig generates as
<cdecl id="4456" addr="0x6efce8" >
<attributelist id="4457" addr="0x6efce8" >
<attribute name="sym_name" value="fn" id="4458" addr="0xbf61b8" />
<attribute name="name" value="fn" id="4459" addr="0xbf61b8" />
<attribute name="decl" value="f(p.q(const).char,va_list)." id="4460" addr="0xbf61b8" />
<parmlist id="4461" addr="0x6efad8" >
<parm id="4462">
<attributelist id="4463" addr="0x6efc08" >
<attribute name="name" value="fmt" id="4464" addr="0xbf61b8" />
<attribute name="type" value="p.q(const).char" id="4465" addr="0xbf61b8" />
</attributelist >
</parm >
<parm id="4466">
<attributelist id="4467" addr="0x6efc98" >
<attribute name="name" value="vl" id="4468" addr="0xbf61b8" />
<attribute name="type" value="va_list" id="4469" addr="0xbf61b8" />
</attributelist >
</parm >
</parmlist >
<attribute name="kind" value="function" id="4470" addr="0xbf61b8" />
<attribute name="type" value="void" id="4471" addr="0xbf61b8" />
<attribute name="sym_symtab" value="0x6d0468" id="4472" addr="0x6d0468" />
<attribute name="sym_overname" value="__SWIG_0" id="4473" addr="0xbf61b8" />
</attributelist >
</cdecl >
and it shows as
attach_function :fn, :fn, [ :string, va_list ], :void
which will fail with undefined local variable or method 'va_list'
I think currently could just comment it out or set va_list
as :pointer
. If someone really wants to use this, then I guess va_list
type needs to be implemented in Ruby FFI
Given the following opaque struct definition:
struct opaque_struct;
typedef struct opaque_struct opaque_struct;
We get the following output
typedef OpaqueStruct.by_value, :opaque_struct
The FFI typedef
command does not support this. It also does not support the following syntax:
typedef OpaqueStruct, :opaque_struct
In the case of opaque structs, no typedef line should be generated.
Given the following C code:
typedef struct typedefed_struct {
int i;
char c;
} typedefed_struct;
struct other_struct {
typedefed_struct s;
int i;
};
int func(typedefed_struct *s);
ffi-swig-generator outputs the following Ruby code:
class TypedefedStruct < FFI::Struct
layout(
:i, :int,
:c, :char
)
end
class OtherStruct < FFI::Struct
layout(
:s, :typedefed_struct,
:i, :int
)
end
attach_function :func, :func, [ :pointer ], :int
This code results in an error from ffi, `TypeError: unable to resolve type 'typedefed_struct'.
ffi-swig-generator should instead generate the following code:
class TypedefedStruct < FFI::Struct
layout(
:i, :int,
:c, :char
)
end
class OtherStruct < FFI::Struct
layout(
:s, TypedefedStruct.by_value,
:i, :int
)
end
attach_function :func, :func, [ TypedefedStruct.ptr ], :int
See: http://groups.google.com/group/ruby-ffi/browse_thread/thread/98eaf51ab0386347
I have a C++ function that takes a pointer to a buffer where the function stores a C-string.
This is what I wrote and got working.
attach_function :GoIO_GetNthAvailableDeviceName, [:pointer, :int, :int, :int, :int], :int
However if I use ffi-swig it generates a :string as the first parameter.
attach_function :GoIO_GetNthAvailableDeviceName, [ :string, :int, :int, :int, :int ], :int
Is there anyway this could work? The function needs an address to a location to store a C-string.
Here's the C++ function:
GOIO_DLL_INTERFACE_DECL gtype_int32 GoIO_GetNthAvailableDeviceName(
char *pBuf, // [out] ptr to buffer to store device name string.
gtype_int32 bufSize, // [in] number of bytes in buffer pointed to by pBuf.
// Strlen(pBuf) < bufSize, because the string is NULL terminated.
gtype_int32 vendorId, // [in] USB vendor id
gtype_int32 productId, //[in] USB product id
gtype_int32 N); //[in] index into list of known devices, 0 => first device in list.
Looking more closely at ffi-swig it's type_spec.rb does expect:
char *string;
to be turned into a :string.
I'm not much of a C programmer but is that correct? It seems in this case it should be a pointer.
Types like these are correctly turned into :string
const char *string;
The choice about turning a pointer into a string appears to be made in ffi-swig at lib/generator/type.rb:74:
def pointer
if @declaration.is_pointer? or @is_pointer > 0
@is_pointer += 1
if @full_decl.scan(/^p\.(.+)/).flatten[0]
ffi_type_from(@full_decl.scan(/^p\.(.+)/).flatten[0])
elsif @full_decl == 'char' and @is_pointer == 2
':string'
else
':pointer'
end
end
end
/usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2503:in const_missing': uninitialized constant FFI::Generator::VERSION (NameError) from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:39:in
do_option'
from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:48:in process_args' from /usr/lib/ruby/1.8/getoptlong.rb:613:in
each'
from /usr/lib/ruby/1.8/getoptlong.rb:610:in loop' from /usr/lib/ruby/1.8/getoptlong.rb:610:in
each'
from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:48:in process_args' from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:22:in
run'
from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/bin/ffi-gen:6
from /usr/bin/ffi-gen:19:in load' from /usr/bin/ffi-gen:19 localhost:~ # ffi-gen --version /usr/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2503:in
const_missing': uninitialized constant FFI::Generator::VERSION (NameError)
from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:39:in do_option' from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:48:in
process_args'
from /usr/lib/ruby/1.8/getoptlong.rb:613:in each' from /usr/lib/ruby/1.8/getoptlong.rb:610:in
loop'
from /usr/lib/ruby/1.8/getoptlong.rb:610:in each' from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:48:in
process_args'
from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/lib/generator/application.rb:22:in run' from /usr/lib/ruby/gems/1.8/gems/ffi-swig-generator-0.3.2/bin/ffi-gen:6 from /usr/bin/ffi-gen:19:in
load'
from /usr/bin/ffi-gen:19
When I've callback defined as
#define COUNT 10
void (*cl)(int list[COUNT]);
swig produces
<attribute name="decl" value="f(a(COUNT).int)." id="19616" addr="0xbf61b8" />
and it appears
callback([ a(COUNT).int ], :void)
but it probably should be
callback([ [:int, 10] ], :void)
only that's not supported yet, see ffi/ffi#385
It appears commit 14ea222 broke callbacks.
Using the following input file:
%module Test
typedef void (*myfunc) (int foo);
With commit 818e921 I get the following result:
Callback_myfunc = callback(:myfunc, [ :int ], :void)
With commit 14ea222 (and up to current master -- a018380) I get an empty file.
Hi!
I have this code:
typedef enum week {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
} week;
and I'm expecting that generator will create named enum:
week = enum(
:sunday,
:monday,
:tuesday,
:wednesday,
:thursday,
:friday,
:saturday)
but it doesn't:
MONDAY = 0
TUESDAY = 1
...
Is it possible to fix it?
A typedef for a pointer to an opaque struct results in invalid ruby being generated.
Given the following C code:
typedef struct opaque_struct* opaque_pointer;
opaque_pointer func(void);
ffi-swig-generator outputs the following ruby:
attach_function :func, :func, [ ], :opaque_pointer
The line defining the :opaque_pointer
as a :pointer
is missing. The output should be as follows:
typedef :pointer, :opaque_pointer
attach_function :func, :func, [ ], :opaque_pointer
Given the following C code:
struct opaque_struct;
struct opaque_struct *alloc_opaque_struct(void);
We currently generate the following ruby code:
class OpaqueStruct < FFI::Struct; end
attach_function :alloc_opaque_struct, :alloc_opaque_struct, [ ], OpaqueStruct.ptr
This code fails when calling alloc_opaque_struct()
because FFI references the layout of the struct, which is not defined.
Instead, the following code should be generated:
attach_function :alloc_opaque_struct, :alloc_opaque_struct, [ ], :pointer
Consider the C code below:
typedef void (*MyCallback) (void *data);
typedef struct {
void (*member) (MyCallback cb);
} MyStruct;
Using the generator you get:
callback(:MyCallback, [ :pointer ], :void)
class MyStruct < FFI::Struct
layout(
:member, callback([ :MyCallback ], :void)
)
end
The ruby code above works fine on MRI 1.8 but not on JRuby or MRI 1.9.
The best way to ensure this works is to generate a constant in enclosing module, and use that on the layout line.
module Foo
extend FFI::Library
MyCallback = callback(:MyCallback, [ :pointer ], :void
class MyStruct < FFI::Struct
layout(:member, callback(MyCallback, :void))
end
end
Given the following code:
int cvStartLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[]);
ffi-swig-generator outputs the following, invalid, ruby code:
attach_function :cvStartLoop, :cvStartLoop, [ callback([ :int, a().p.char ], :int), :int, :pointer ], :pointer
Note the a().p.char
as the second argument within the callback.
ffi-swig-generator should output:
attach_function :cvStartLoop, :cvStartLoop, [ callback([:int, :pointer], :int), :int, :pointer ], :pointer
Minimal Example:
%module test
%{
module Test
%}
enum foo {
FOO,
BAR = FOO
};
%{
end
%}
Generates to
module Test
foo = enum :foo, [
:foo,
:bar, FOO, // fails here, obviously
]
FOO = 0
BAR = FOO
end
which doesn't work. I am not completely sure that ffi-swig-generator is at fault here, but it is my best idea.
Pointer typedefs are not being generated correctly. Given the following c typedef:
typedef int * pInt
This is the ruby code that is generated:
typedef :int, :pInt
This is what should be generated:
typedef :pointer, :pInt
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.