[英]Using swig c++ to python with no access to library source
我是 swig 的新手,并尝试搜索文档以寻找答案,但我要么错过了它,要么在看到它时没有认出答案。
我有一个来自第三方的大型 C++ 库,除了头文件我没有源代码。 我需要从 python 访问一些 API,其中一些 API 具有类似于以下内容的函数原型:
int foo(int& a, int& b, int& c);
我创建了一个 .i 文件,如下所示:
%module myWrapper
%{
#include libraryHeader.h
%}
extern int foo(int& m1, int& m2, int& bf);
这通过 swig、g++ 编译器和链接器没有问题。 我可以将模块导入 python,但是当我调用它时,出现以下错误:
类型错误:在方法“foo”中,“int &”类型的参数 1
我已经声明了 3 个 int 变量,如 m1 = 0; m2 = 0; bf = 0 所以我传入了一些东西。有没有办法使用 typemaps.i 库或明确使用 typemaps 来做到这一点? 文档在这个主题上似乎有点含糊。
提前致谢,保罗
SWIG 需要提示参数不是简单的输入。 这些提示由类型映射提供。 您需要定义类型映射或使用预定义的类型映射(请参阅typemaps.i )。
下面是一个例子:
%module test
%{
int foo(int& a, int& b, int& c)
{
int ret = a + b + c;
a = 10;
b = 20;
c = 30;
return ret;
}
%}
%include <typemaps.i>
int foo(int& INOUT, int& INOUT, int& INOUT);
使用INOUT
映射,Python 可以将整数传递给带有 for int*
或int&
的函数,返回值将是原始返回值和任何输出参数的元组。 编译上面的 SWIG 结果并在 Python 中使用如下所示:
>>> import test
>>> test.foo(1,2,3)
[6, 10, 20, 30]
您可以使用如下代码更新变量:
>>> a,b,c = 1,2,3
>>> r,a,b,c = test.foo(a,b,c)
>>> r
6
>>> a,b,c
(10, 20, 30)
请注意,您还可以%apply
现有类型映射应用于类型,因此如果使用%include "libraryHeader.h"
而不是直接声明函数,您可以使用以下内容将INOUT
类型%include "libraryHeader.h"
一般应用于所有int&
参数:
%apply int &INOUT { int& };
%include "libraryHeader.h"
我已经在这个线程和固执的其他人的帮助下回答了我自己的问题。 我创建了一个 .i 文件,如下所示:
%module myWrapper
%include "typemaps.i"
%{
#include "libraryHeader.h"
typedef unsigned int MY_RESULT;
%}
typedef unsigned int MY_RESULT;
extern MY_RESULT MyGetVersion(int& OUTPUT, int& OUTPUT, int& OUTPUT, int&
OUTPUT);
extern MY_RESULT MyGetDeviceDriverVersion(int deviceType, int& OUTPUT, int&
OUTPUT, int& OUTPUT, int& OUTPUT);
它干净利落地执行、编译和链接,一个非常简单的 python 测试脚本返回预期的结果。 该脚本如下所示:
#!/usr/bin/python3
import myWrapper
ret = 0 # function return value
maj = 0 # major version
min = 0 # minor version
bugFix = 0 # bug fix number
build = 0 # build
#
# Because of the typemap defined in myWrapper.i, we don't need to supply function arguments.
# The results are returned by the function call as seen below...
#
ret, maj, min, bugFix, build = myWrapper.MyGetVersion()
#
# See what we got
#
print('function return: '+str(ret)+' Maj: '+str(maj)+' Min: '+str(min)+' BugFix:'+str(bugFix)+' Build: '+str(build))
#
# This call returns the same information that the call above does but adds an input argument
# that specifies the Device Catagory. 0 is PCI
#
ret, maj, min, bugFix, build = myWrapper.MyGetDeviceDriverVersion(0)
print('function return: '+str(ret)+' Maj: '+str(maj)+' Min: '+str(min)+' BugFix: '+str(bugFix)+' Build: '+str(build))
运行此脚本的结果提供了预期的结果:
function return: 0 Maj: 5 Min: 31 BugFix: 0 Build: 109
function return: 0 Maj: 4 Min: 26 BugFix: 4 Build: 253
非常感谢大家的帮助,我希望这个答案可以帮助别人。
保罗
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.