2012-07-22 44 views
1

我swig.i文件这样的:与SWIG绑定 - 绑定Typedef的类型不正确

%module ogr_api 

%{ 
#include "ogr_api.h" 
%} 

%inline %{ 
typedef void *OGRSFDriverH; 
%} 

/* OGRSFDriverRegistrar */ 

OGRDataSourceH OGROpen(const char *, int, OGRSFDriverH *)` 

,我得到了以下的.c包装:

... 
SWIGEXPORT void * D_OGROpen(char * jarg1, int jarg2, void * jarg3) { 
... 

也就是说痛饮转换OGRSFDriverH只是无效*。我需要保存类型名称。我怎么能这样做?

另外我在第一个参数中损失const,但这是下一个问题。

+0

我认为你的目标语言是Java,尽管在这种情况下它应该没关系,但通常在SWIG问题中值得一提,因为某些功能/选项是语言特定的。 – Flexo 2012-07-22 17:14:46

+0

为了以防万一 - 我的目标语言是D – Noname 2012-07-23 14:27:13

+0

也许你应该尝试一下DStep - https://github.com/jacob-carlborg/dstep – DejanLekic 2012-07-23 22:30:28

回答

0

假设我理解正确你的问题,你有一些不透明的“处理”,在C是真的typedef s到void*,但在你生成的接口要强制执行强类型检查。 (请注意,默认行为在这里是正确的,因为它允许恰好镜像C的使用)。您希望防止意外地将一种类型的句柄提交给采用“不同”void*的函数,即将typedef作为strong typedef类型。

你可以用SWIG做到这一点,而不会有太多的麻烦。关键要记住的是,您给SWIG的接口文件并不总是必须与C类型完全匹配,只要最终生成的代码是正确的且合法的。

我举了一个例子来说明这一点。给定一个头文件,它在原理上与您ogr_api.h大概相似:

#include <stdio.h> 

typedef void * HandleType1; 
typedef void * HandleType2; 

void foo(HandleType1) {printf("foo\n");} 
void bar(HandleType2) {printf("bar\n");} 

你只想能够调用fooHandleType1barHandleType2

我用下面的接口来获得这样的行为:

%module test 

%{ 
#include "test.h" 
%} 

%nodefaultctor HandleType1; 
struct HandleType1 {}; 
%nodefaultctor HandleType2; 
struct HandleType2 {}; 

void foo(HandleType1*); 
void bar(HandleType2*); 

%inline { 
    // just for testing - presumably you have a creator in your real API 
    HandleType1* geth1() { return NULL; } 
    HandleType2* geth2() { return NULL; } 
} 

是获取此生成的代码是完全正常的,虽然,因为它不尝试做任何事情不能用void*完成和它们都被当作包装器中的指针来处理。

需要%nodefaultctor来防止SWIG试图根据我们告诉它的谎言来构造一个新的句柄,否则会出现编译器错误。 (你可能想压制析构函数,或者自定义它,因为这将调用free)。

它生成一个Java接口,只允许为每个函数使用正确的句柄。我测试了这一点:

public class run { 
    public static void main(String[] args) { 
    System.loadLibrary("test"); 
    test.foo(test.geth1()); 
    //test.bar(test.geth1()); 
    //test.foo(test.geth2()); 
    test.bar(test.geth2()); 
    } 
} 

这有点一招,但它的作品,看看获取生成说服自己的包装。

编译并按预期运行。已注释的行会按照您的希望提供错误。


对于d具体的解决方案,在那里我明白typedef给人以强烈的typedef(不像alias这更像是用C typedef)我认为你可以使用类似:

%module test 

typedef void * HandleType1; 
typedef void * HandleType2; 

%pragma(d) proxydmodulecode = %{ 
    typedef void * HandleType1; 
    typedef void * HandleType2; 
%} 

%typemap(dtype) HandleType1* "HandleType1"; 
%typemap(dtype) HandleType2* "HandleType2"; 

void foo(HandleType1* h1); 
void bar(HandleType2* h2); 

要生成你想要的接口。类型映射修改D接口中使用的类型,%pragmatypedef插入生成的接口的(代理)部分。

+0

你明白我的问题了。我得到我想要的 - 强大的类型检查,它工作得很好。但是使用class是纯指针会破坏我的代码(我的目标语言是D)。你能举一个例子来说明在这种情况下如何避免使用类? – Noname 2012-07-23 14:21:32

+0

但SWIG生成的类包装我的类型... – Noname 2012-07-23 14:58:47

+0

看起来像它可能想''typemap(dtype)HandleType1 *“$ imdodule.HandleType1”;'等等,如果你在'imdmodulecode'中保留'typedef'。 – Flexo 2012-07-23 15:50:54