假设我已经正确理解了您的问题,那么您在 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("foo\n");}
void bar(HandleType2) {printf("bar\n");}
您希望只能foo
使用 aHandleType1
和bar
a调用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(不像在 Calias
中更像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);
To generate the interface you want. The typemaps modify what the types used in the D interface are, the %pragma
inserts the typedef
into the (proxy) part of the generated interface.