[英]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.