Использование Swig C ++ для Python без доступа к источнику библиотеки - PullRequest
0 голосов
/ 14 января 2019

Я новичок в глотке и пробовал найти документацию для ответа, но я либо пропустил его, либо не узнал ответ, когда увидел его.

У меня есть большая библиотека C ++ от стороннего производителя, для которой у меня нет исходного кода, кроме заголовка. Мне нужно получить доступ к нескольким API из Python, и некоторые из 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, но когда я вызываю его, я получаю следующую ошибку:

TypeError: в методе 'foo', аргумент 1 типа 'int &'

Я объявил 3 переменные типа int, например, m1 = 0; м2 = 0; bf = 0, поэтому я передаю что-то in. Есть ли способ сделать это, используя библиотеку typemaps.i или явно используя typemaps? Документация кажется немного расплывчатой ​​по этому вопросу.

Заранее спасибо, Пол

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Я ответил на свой вопрос с помощью других на эту тему и упрямство. Я создал .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

Большое спасибо всем за помощь, и я надеюсь, что этот ответ может помочь кому-то еще.

Пол

0 голосов
/ 16 января 2019

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 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 сопоставления типов ко всем int& параметрам:

%apply int &INOUT { int& };
%include "libraryHeader.h"
...