如何使用 SWIG 接口访问 python 中的 C++ typedef'd 结构



我正在尝试配置我的SWIG接口以公开所有定义的typedef。

示例:对于我的C++头文件中的以下内容,我希望我的python代码能够创建对象A、B、C、D、E。

//MyHeader.h
struct Common
{
uint8_t     eId;
};
typedef Common A, B, C, D, E;

我在头文件中测试了以下结构,通过SWIG接口可用的对象是Test、Test2Typedef和Test3Typedef1,但不是TestTypedef、Test2、Test3或Test3Typedef2。

//MyHeader.h
struct Test {
uint8_t uValue;
};
typedef Test TestTypedef;
typedef struct Test2 {
uint8_t uValue;
} Test2Typedef;
typedef struct Test3 {
uint8_t uValue;
} Test3Typedef1, Test3Typedef2;

我已经尝试将以下typedef添加到我的.I文件中,但仍然无法访问TestTypedef:

//MyHeader.i
%{
#include "MyHeader.h"
typedef Test TestTypedef;
%}
typedef Test TestTypedef;
%include "MyHeader.h"

一般来说,SWIG尽量在目标语言中反映C的行为。不过,当typedef语义没有通用的大小写映射到SWIG目标的许多语言中时,有时这有点棘手。在这个特定的例子中,尽管您仍然可以使用两个可能的选项之一,在Python中实现您想要的行为。为了简化事情,尽管您希望在头中更加一致,所以要么始终对TestN结构进行typedef,要么从不对其进行typedef。

首先,您可以在%pythoncode中编写一点额外的Python代码,以确保Python中的每种类型都有一个与您期望的相匹配的别名。以下界面显示:

%module test

%inline %{
struct Test {
uint8_t uValue;
};
typedef Test TestTypedef;
struct Test2 {
uint8_t uValue;
};
typedef Test2 Test2Typedef;
struct Test3 {
uint8_t uValue;
};
typedef Test3 Test3Typedef1, Test3Typedef2;
%}
%pythoncode %{
TestTypedef = Test
Test2Typedef = Test2
Test3Typedef1 = Test3
Test3Typedef2 = Test3
%}

然而,另一种方法是在C++层中进行一些欺骗。在现实中,我们所要做的就是确保SWIG生成我们想要的接口,并且它都是合法、正确、可编译的C++代码。然而,如果我们在C++代码的真实情况上对SWIG撒谎,那也没关系。因此,在实践中,如果我们声称我们的每个typedef实际上都是一个派生类,但实际上它们只是typedef,那么我们最终仍然会从中获得一个完美的工作界面。此外,在目标语言中,大多数东西都会更具类型安全性,这可能很好:

%module test

%{
// This is what the C++ compiler sees:    
struct Test {
uint8_t uValue;
};
typedef Test TestTypedef;
struct Test2 {
uint8_t uValue;
};
typedef Test2 Test2Typedef;
struct Test3 {
uint8_t uValue;
};
typedef Test3 Test3Typedef1, Test3Typedef2;
%}
// This is the lie we tell SWIG, but it's compatible with what the C++ code really is doing
struct Test {
uint8_t uValue;
};
struct Test2 {
uint8_t uValue;
};
struct Test3 {
uint8_t uValue;
};
struct Test2Typedef : Test2 {};
struct Test3Typedef1 : Test3 {};
struct Test3Typedef2 : Test3 {};

其中任何一个都可以让我们运行以下Python代码:

import test
a = test.Test3Typedef2()

如果是我这样做,我会为typedef生成定义一个宏:

#ifndef SWIG
#define MAKE_TYPEDEF(original, renamed) typedef original renamed
#else
#define MAKE_TYPEDEF(original, renamed) struct renamed : original {}
#endif 

它可以存在于头文件中,并允许您仍然使用%include

最新更新