正如标题问题所暗示的那样,我正在尝试使用 SWIG 来包装在 C++ 中定义的函数,该函数具有对用作输入和输出的结构向量的引用作为其变量之一(在 C++ 中很常见),因此该函数可以是在 Python 中使用。
我将 SWIG 版本 4.0.0 和 Python 3.6 64 位与 Visual Studio 2015(v140 编译器)一起使用。
上面突出显示的问题是 C++ 中的常见做法,因此无法找到一个示例来描述如何使用 SWIG 包装 C++ 中定义的函数以在 python 中使用来实现它,这令人惊讶。以下链接是我能找到的最接近的示例:
但他们并没有帮助解决下面描述的问题:
我尝试的第一件事是在 SWIG 接口文件中使用带有 INOUT 选项的类型映射,该文件由以下内容给出:
/* File : ParserLib.i */
%module ParserLib
%include "typemaps.i"
%include "std_vector.i"
%{
#include "Structures.h"
#include "Read.h"
%}
%apply int *INOUT { int &nNumber };
%apply std::vector<stData> *INOUT { std::vector<stData> &data };
%include "Structures.h"
%include "Read.h"
%template(Struct) std::vector<stData>;
其中 stData 是在 Structures.h 中定义的结构,而同时引用 nNumber 和数据的函数声明在 Read.h 中。
但是,当我尝试编译接口文件时,我收到警告消息:
警告 453:无法应用 (std::vector< stData > *INOUT)。没有定义类型映射。
所以我做了一些进一步的搜索,找到了博客:
如何使用 SWIG 类型映射通过 P/Invoke 将结构成员从 C++ 编组到 C#?
这基本上在回应中说:
“......您是否可以使用结构向量来代替?通过简单地包含 std_vector.i 和相关类型映射,我在传递结构或自定义对象的向量时没有问题,例如:
%include "std_vector.i
%typemap(MyClassVec) std::vector<MyClass>;
"
所以我尝试添加:
%typemap(vecOfStruct) std::vector<stData>;
到应用调用上方位置的接口文件(上面提供),但在编译接口文件时仍然得到相同的警告消息。
现在我知道这只是一条警告消息,并且接口文件仍然可以编译,但是我没有得到 Python 中在将 apply 与 INOUT 一起使用时所期望的通常行为,即在函数中输入一个变量并获取输出由函数返回。
我还应该指出模板定义:
%template(vecOfStruct) std::vector<stData>;
允许我在 Python 中定义一个结构向量并传递给函数调用——这是必需的,否则我会得到 typedef 不匹配错误——它实际上运行,但是在 Python 中工作时我得到了一些不寻常的行为。
下面是我用来运行 SWIG 包装的 c++ 库的 Python 脚本示例:
from ParserLib import vecOfStruct, Read
vecOfStruct = vecOfStruct()
Read = Read()
file = "file path and name to be read in"
tempNum = Read.ReadData(file, vecOfStruct, 0)
print(int(tempNum[1]))
v0 = vecOfStruct[0].data1
print(v0)
tempNum = Read.ReadData(file, vecOfStruct, tempNum[1])
现在这里的函数调用将 tempNum 填充为具有值的列表(或数组):
[<Swig Object of type 'BOOL *' at 0x0000000005248300>, 100],
因此为什么要调用列表中的第二个元素以打印结果;我不确定第一个元素指的是什么。有趣的是,我仍然能够从 vecOfStruct(python 中的一个类)访问信息,而无需将其实际设置为函数调用的返回值。但是当我尝试调用 read 函数并将 vecOfStruct 作为输入传递时,它不会从第一个函数调用附加到(现在填充的)vecOfStruct。
目的是将函数调用为:
Struct, tempNum = Read.ReadData(1, Struct, 0)
在一个循环中,并且能够将 vecOfStruct 传回,让它附加来自不同文件的数据。