与SWIG绑定 - typedef'ed类型绑定不正确

时间:2012-07-22 14:58:50

标签: d typedef swig

我有这样的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,但这是下一个问题。

1 个答案:

答案 0 :(得分:0)

假设我已经正确理解了你的问题,你有很多不透明的“句柄”,在C中真的是typedefvoid*,但在你生成的界面中你想强制执行更强的类型检查。 (请注意,此处的默认行为是正确的,因为它允许使用完全镜像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");}

您希望只能使用fooHandleType1 bar来呼叫HandleType2

我使用以下界面来获取此类行为:

%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插入生成的接口的(代理)部分。