簡體   English   中英

在無法訪問庫源的情況下使用 swig c++ 到 python

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM