与SWIG绑定-类型定义的类型绑定不正确 [英] Binding with SWIG - typedef'ed types bound incorrectly

查看:73
本文介绍了与SWIG绑定-类型定义的类型绑定不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的swig.i文件:

I have swig.i file like that:

%module ogr_api

%{
#include "ogr_api.h"
%}

%inline %{
typedef void *OGRSFDriverH;
%}

/* OGRSFDriverRegistrar */

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

,我得到以下.c包装器:

and I get the following .c wrapper:

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

SWIG将OGRSFDriverH转换为void *。我需要保存类型名称。我该怎么办?

That is SWIG translates OGRSFDriverH to just void*. I need to save the type name. How could I do it?

我在第一个参数中也失去了const,但这是下一个问题。

Also I loss const in the first argument, but this is the next question.

推荐答案

假设我正确地理解了您的问题,您有许多不透明的句柄,它们在C中实际上是 typedef s void * ,但是在生成的界面中,您想执行更严格的类型检查。 (请注意,这里的默认行为是正确的,因为它允许使用与C完全相同的用法)。您想防止意外地给采用不同 void * 的函数提供一种句柄,即公开 typedef 作为一种 strong typedef a>。

Assuming I've understood your question correctly you have a number of opaque "handles" that in C are really typedefs to void*, but in your generated interface you want to enforce stronger type checking. (Note that the default behaviour is correct here in that it permits usage that exactly mirrors C). You want to prevent a handle of one sort accidentally being given to a function that takes a "different" void*, i.e. expose the typedef as a sort of strong typedef.

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

You can do that with SWIG without too much trouble. The key thing to remember is that the interface file you give SWIG doesn't always have to exactly match the real C types, so long as the code that gets produced at the end is correct and legal still.

我举了一个例子来说明这一点。给定一个头文件,原理上可能与您的ogr_api.h类似:

I put together an example to illustrate this. Given a header file, which is presumably similar in principle to your ogr_api.h:

#include <stdio.h>

typedef void * HandleType1;
typedef void * HandleType2;

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

您只想使用 HandleType1 bar HandleType2

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

I used the following interface to get such behaviour:

%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 * 无法完成的任何事情,它们都只作为包装器中的指针处理。

The code that gets generated by this is perfectly fine though since it doesn't try to do anything that can't be done with void* and they're both handled as just pointers in the wrapper.

需要使用%nodefaultctor 来防止SWIG尝试根据我们所说的谎言来构造新的句柄,否则将导致编译器错误这个。 (您可能也想抑制析构函数,或对其进行自定义,因为它将调用 free )。

The %nodefaultctor is needed to prevent SWIG from trying to construct a new handle based on the lies we told it, you'd get a compiler error with out this. (You probably want to suppress the destructor too, or customise it since that will be calling free).

其中生成一个Java接口,该接口仅允许将正确的句柄用于每个函数。我用以下方法对此进行了测试:

Which generates a Java interface that only allows the correct handle to be used for each function. I tested this with:

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());
  }
}

这是一个小技巧,但是有效,

It's a bit of a trick, but it works, have a look at the wrapper that gets generated to convince yourself.

编译并按预期运行的程序。注释掉的行会产生您希望的错误。

Which compiled and ran as expected. The commented out lines give errors as you'd hope.

对于D特定的解决方案,我理解 typedef 提供了强大的typedef(与 alias 不同,后者更像是 typedef C)我认为您可以使用类似的东西:

For a D specific solution, where I understand typedef gives a strong typedef (unlike alias which is more like typedef in C) I think you can use something like:

%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 插入到(代理)中生成的界面的一部分。

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.

这篇关于与SWIG绑定-类型定义的类型绑定不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆