我有类似的swig.I文件:
%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) {
...
这就是SWIG将OGRSFDriverH翻译为void。我需要保存类型名称。我该怎么做?
我在第一个论点中也失去了const,但这是下一个问题。
假设我正确理解了你的问题,你有很多不透明的"句柄",在C中它们实际上是typedef
到void*
,但在你生成的接口中,你希望强制执行更强的类型检查。(请注意,这里的默认行为是正确的,因为它允许使用完全镜像C的方法)。您希望防止一种类型的句柄意外地被赋予采用"不同"void*
的函数,即将typedef
公开为某种强typedef。
使用SWIG可以做到这一点,而不会遇到太多麻烦。需要记住的关键是,您给SWIG的接口文件并不总是必须与真正的C类型完全匹配,只要最后生成的代码是正确合法的。
我举了一个例子来说明这一点。给定一个头文件,其原理可能与您的ogr_api.h类似:
#include <stdio.h>
typedef void * HandleType1;
typedef void * HandleType2;
void foo(HandleType1) {printf("foon");}
void bar(HandleType2) {printf("barn");}
您希望只能用HandleType1
调用foo
,用HandleType2
调用bar
。
我使用以下界面来获得这样的行为:
%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接口中使用的类型,%pragma
将typedef
插入生成接口的(代理)部分。