Как правило, SWIG пытается максимально точно отразить поведение C на целевом языке. Иногда это немного сложно, хотя нет общего отображения семантики typedef на многие языки, на которые нацелена SWIG. В этом конкретном случае вы все равно можете добиться нужного вам поведения в Python, используя один из двух возможных вариантов. Чтобы упростить вещи, вы захотите быть более последовательными в своем заголовке, поэтому либо всегда набирайте структуры TestN
, либо никогда не печатайте их.
Во-первых, вы можете написать немного дополнительного кода Pythonвнутри %pythoncode
, который обеспечивает псевдоним для каждого типа в 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 ++. Однако не имеет значения, если мы лжем SWIG о том, на что действительно похож наш код C ++. Таким образом, на практике, если мы утверждаем, что каждый из наших typedefs на самом деле является производным классом, но на самом деле это просто typedefs, мы все равно получим прекрасно работающий интерфейс. И в качестве бонуса, в основном, на целевом языке вещи будут более безопасными, что, вероятно, хорошо:
%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
still.