Typedef,Ruby和SWIG

时间:2015-09-04 20:00:58

标签: c++ ruby swig

我试图为某些C ++类生成Ruby包装器。生成成功,所有方法都被创建,但问题是一小部分C ++方法使用它:

/* FPU settings ------------------------------------------------------------*/

当我在irb中运行一个返回Count的方法时,我会得到这样的结果:

#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
  #endif

我期待一个数字......我尝试使用反射来看看我是否能以某种方式获得价值,但没有雪茄。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

typedef阻止SWIG确定Counter是一个可以直接转换的未装箱类型。如果没有其他信息,它会将Counter视为一种抽象对象类型,只能由库中的函数生成和使用。

您需要告诉SWIG Counter等同于内在longlong long

typemap是SWIG的做法。此外,SWIG语言本身提供typedef来声明Counter及其底层内在类型的等价性。

以下是它的工作原理。您应该能够轻松地将其转换为解决问题的方法:

// hacking.i
%module hacking
%{
// "Simulation" of the header included verbatim in the glue code.
#ifdef USE_LONGLONG_COUNTS
typedef unsigned long long Count;   /* a count of something */
#else
typedef unsigned long Count;        /* a count of something */
#endif
Count foo(Count count) { return count; }
%}

// The typemaps...
%typemap(in) Count n {
#ifdef USE_LONGLONG_COUNTS
 $1 = ULL2INT($input);
#else
 $1 = ULONG2INT($input);
#endif
}

%typemap(out) Count {
#ifdef USE_LONGLONG_COUNTS
 $result = ULL2NUM($1);
#else
 $result = ULONG2NUM($1);
#endif
}

// Now tell SWIG about the type equivalences and function prototype.
#ifdef USE_LONGLONG_COUNTS
typedef unsigned long long Count;   /* a count of something */
#else
typedef unsigned long Count;        /* a count of something */
#endif
Count foo(Count count);

请注意,如果定义了USE_LONGLONG_COUNTS,则您使用的Ruby必须支持long long类型。不是全部都做。

类型地图功能强大,有很多选项。您没有提供足够的信息来为您的问题提供更具体的解决方案。引用Ruby SWIG docs是关于所有可能的事情,直到你提供更多。

现在要构建,创建一个文件:

# extconf.rb
require 'mkmf'
create_makefile('hacking')

并且(如果您需要-DUSE_LONGLONGCOUNTS,则省略unsigned long):

$ swig -c++ -DUSE_LONGLONG_COUNTS -ruby -o wrap.cpp hacking.i
$ ruby extconf.rb
$ make
compiling wrap.cpp
linking shared-object hacking.bundle
$ make install
/usr/bin/install -c -m 0755 hacking.bundle ...  
$ irb
2.2.1 :001 > require 'hacking'
 => true 
2.2.1 :002 > Hacking.foo(1234567890123454567)
 => 1234567890123454567 

答案 1 :(得分:1)

这很奇怪。

你确定swig是&#34;看到&#34;你typedef的{​​{1}}?因为否则Count只是swig一无所知的某种类型,它会将其包装为指向C对象的指针,在这种情况下,swig应该生成警告。

无论如何,我刚刚从您的问题中创建了一个示例并按照swig 3.0.7进行了测试,对我来说它只是按预期工作(没有类型地图):

dummy.i(其他案例的评论Count

#define USE_LONGLONG_COUNTS

extconf.rb

%module dummy

%inline %{

#define USE_LONGLONG_COUNTS

#ifdef USE_LONGLONG_COUNTS
typedef unsigned long long Count;   /* a count of something */
#else
typedef unsigned long Count;        /* a count of something */
#endif

Count returnCount(Count count) { return count; }

%}

要编译并运行ruby,我会这样做:

require 'mkmf'
create_makefile('dummy')

然后在swig -c++ -ruby dummy.i ruby extconf.rb make irb ,我可以这样做:

irb

请注意,irb(main):001:0> require_relative 'dummy' => true irb(main):002:0> Dummy.returnCount(2**64-1) => 18446744073709551615 irb(main):003:0> Dummy.returnCount(-1) => 18446744073709551615 irb(main):004:0> Dummy.returnCount(2**64) TypeError: Expected argument 0 of type Count, but got Bignum 18446744073709551616 in SWIG method 'returnCount' from (irb):4:in `returnCount' from (irb):4 from /usr/bin/irb:12:in `<main>' unsigned long long在我的系统/编译器上都是64位,而且我的ruby版本支持这些。如果不是这样,转换可能不起作用,我也不知道。

在任何情况下,正如另一个答案所声称的那样,导致问题的不是unsigned long