作为一般规则,SWIG 尝试在目标语言中尽可能地反映 C 的行为。有时这有点棘手,尽管没有将 typedef 语义映射到许多 SWIG 目标语言的一般情况下。在这个特定的例子中,尽管您仍然可以使用两种可能的选项之一来实现您在 Python 中寻找的行为。为了简化事情,尽管您希望在标题中更加一致,所以要么总是 typedef TestN 结构,要么永远不要 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。