Я пытаюсь выучить SWIG (http://www.swig.org/), чтобы расширить / открыть имеющуюся у меня библиотеку C ++ для Python и Java языков.
Перед тем, как начать эту работу, я начал с простого примера SWIG (http://www.swig.org/tutorial.html) и получил, что это работает.
См. Ниже (на моей системе вы можете увидеть swig woks и что я могу загрузить «примерный» модуль в Python оболочку):
linux{me}% swig -python example.i
linux{me}% gcc -c -fPIC example.c example_wrap.c / -I/usr/include/python2.7
gcc: warning: /: linker input file unused because linking not done
linux{me}% gcc -c -fPIC example.c example_wrap.c -I/usr/include/python2.7
linux{me}% ld -shared example.o example_wrap.o -o _example.so
linux{me}% python
Python 2.7.5 (default, Aug 2 2016, 04:20:16)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import example
example.fact(5)
120
example.my_mod(5)
Traceback (most recent call last):
File "", line 1, in
TypeError: my_mod() takes exactly 2 arguments (1 given)
example.my_mod(7,3)
1
example.get_time()
'Fri Feb 28 14:54:08 2020\n'
Все Хорошо, теперь следующим шагом является предоставление класса C ++, поэтому я изначально следовал этому руководству (https://realmike.org/blog/2010/07/18/python-extensions-in-cpp-using-swig/). По сравнению с официальными документами SWIG в этом учебнике было пропущено несколько шагов, например, загрузите совместно используемый libray .so, чтобы Python мог вызвать «import» в библиотеке, мы вернемся к этому позже ...
Я сделал несколько изменений в SomeClass.h, чтобы добавить константы "#define TypeBool 0" et c ...
Вот соответствующий фиктивный заголовок C ++:
#ifndef _SOME_CLASS_H_
#define _SOME_CLASS_H_
class SomeClass {
public:
SomeClass();
SomeClass(int a, int b);
virtual ~SomeClass();
void MethodA(int a = -1);
void MethodB(int b = -1);
void setType(int type);
int GetValA();
int GetValB();
int GetType();
private:
int mValA;
int mValB;
int type;
};
#endif // _SOME_CLASS_H_
Вот соответствующий файл класса, который реализует SomeClass.h:
#include "SomeClass.h"
//refactor to use enum
#define TypeBool 0
#define TypeChar 1
#define TypeByte 2
#define TypeInt 3
#define TypeShort 4
#define TypeFloat 5
#define TypeDouble 6
#define TypeString 7
#define TypeComposite 8
SomeClass::SomeClass() {
mValA = -1;
mValB = -1;
}
SomeClass::~SomeClass() {
}
void SomeClass::MethodA(int a)
{
mValA = mValA * -1;
}
void setType(int type)
{
switch (type)
{
case 0:
type = TypeBool;
break;
case 1:
type = TypeChar;
break;
case 2:
type = TypeByte;
break;
case 3:
type = TypeInt;
break;
case 4:
type = TypeShort;
break;
case 5:
type = TypeFloat;
break;
case 6:
type = TypeDouble;
break;
case 7:
type = TypeString;
break;
case 8:
type = TypeComposite;
break;
}
}
void SomeClass::MethodB(int b)
{
mValB = b;
}
int SomeClass::GetValA()
{
return mValA;
}
int SomeClass::GetValB()
{
return mValB;
}
int SomeClass::GetType()
{
return type;
}
Попытка # 1 Здесь необходим SWIG-файл "интерфейса", основанный на на (https://realmike.org/blog/2010/07/18/python-extensions-in-cpp-using-swig/) или http://www.swig.org/Doc4.0/SWIGDocumentation.pdf на страницах 25-32.
%module mymodule
%{
#include "SomeClass.h"
%}
%include "SomeClass.h"
1) Затем я запускаю команду:
swig -c ++ - python -I / home / me / NetBeansProjects / example mymodule .i
Этот комманд работает и, кажется, создает python & cpp автоматически сгенерированные оболочки:
-rw-r - r-- 1 me linuxlusers 350 3 марта 15:53 mymodule.i -rw-r - r-- 1 me linuxlusers 2864 3 марта 15:55 mymodule.py -rw-r - r-- 1 me linuxlusers 121327 3 марта 15:55 mymodule_wrap.cxx
2) Затем я компилирую:
g ++ - c -fPI C SomeClass. cpp mymodule_wrap.cxx -I /usr/include/python2.7
, который создает объектные файлы:
-rw-r - r-- 1 me linuxlusers 60136 3 марта, 15:56 mymodule_wrap. o -rw-r - r-- 1 me linuxlusers 4384 3 марта 15:56 SomeClass.o
3) Затем я объединяю свои объектные файлы в файл общей библиотеки ".so" и создаю эта общая библиотека доступна для всей системы, поэтому я могу загрузить ее из Python:
linux{me}% ld -shared mymodule_wrap.o -o _mymodule.so
4) Наконец, я вызываю python shell из моего коммандера d строка и попытка импортировать мой модуль :
linux{me}% python
Python 2.7.5 (default, Aug 2 2016, 04:20:16)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mymodule
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "mymodule.py", line 15, in <module>
import _mymodule
ImportError: ./_mymodule.so: undefined symbol: __gxx_personality_v0
>>>
Вы можете увидеть ошибку: ImportError: ./_mymodule.so: неопределенный символ: __gxx_personality_v0.
Попытка $ 2 (я переписал файл интерфейса с помощью. cpp внедрение в теге% inline):
%module mymodule
%{
#include "SomeClass.h"
%}
%include "SomeClass.h"
%constant TypeBool 0
%constant TypeChar 1
%constant TypeByte 2
%constant TypeInt 3
%constant TypeShort 4
%constant TypeFloat 5
%constant TypeDouble 6
%constant TypeString 7
%constant TypeComposite 8
%inline %{
SomeClass::SomeClass() {
mValA = -1;
mValB = -1;
}
SomeClass::~SomeClass() {
}
void SomeClass::MethodA(int a)
{
mValA = mValA * -1;
}
void setType(int type)
{
switch (type)
{
case 0:
type = TypeBool;
break;
case 1:
type = TypeChar;
break;
case 2:
type = TypeByte;
break;
case 3:
type = TypeInt;
break;
case 4:
type = TypeShort;
break;
case 5:
type = TypeFloat;
break;
case 6:
type = TypeDouble;
break;
case 7:
type = TypeString;
break;
case 8:
type = TypeComposite;
break;
}
}
void SomeClass::MethodB(int b)
{
mValB = b;
}
int SomeClass::GetValA()
{
return mValA;
}
int SomeClass::GetValB()
{
return mValB;
}
int SomeClass::GetType()
{
return type;
}
%}
Я снова запустил команды и компиляцию swig, однако получил та же ошибка:
linux{me}% swig -c++ -python -I/home/me/NetBeansProjects/example mymodule.i
linux{me}% g++ -c -fPIC SomeClass.cpp mymodule_wrap.cxx -I/usr/include/python2.7
linux{me}% ld -shared mymodule_wrap.o -o _mymodule.so
linux{me}% python
Python 2.7.5 (default, Aug 2 2016, 04:20:16)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mymodule
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "mymodule.py", line 15, in <module>
import _mymodule
ImportError: ./_mymodule.so: undefined symbol: __gxx_personality_v0
>>>
KeyboardInterrupt
>>>
Попытка 3 (я переписал файл интерфейса с заголовком .h в теге% inline):
%module mymodule
%{
#include "SomeClass.h"
%}
%include "SomeClass.h"
%constant TypeBool 0
%constant TypeChar 1
%constant TypeByte 2
%constant TypeInt 3
%constant TypeShort 4
%constant TypeFloat 5
%constant TypeDouble 6
%constant TypeString 7
%constant TypeComposite 8
%inline %{
class SomeClass {
public:
SomeClass();
SomeClass(int a, int b);
virtual ~SomeClass();
void MethodA(int a = -1);
void MethodB(int b = -1);
void setType(int type);
int GetValA();
int GetValB();
int GetType();
private:
int mValA;
int mValB;
int type;
};
%}
Опять получил та же ошибка (ImportError: ./_mymodule.so: неопределенный символ: __gxx_personality_v0.) как и две другие попытки выше.
Я попытался установить флаги компилятора, как рекомендовано в ошибка «неопределенный символ: __cxa_pure_virtual» при загрузке библиотеки из java
Однако я получил ту же ошибку.
1) Как я могу устранить эту ошибку?
Попытка # 4 В некотором смысле решения:
Я написал весь новый, более простой класс, основанный на другом онлайн-руководстве, , но без перегруженных конструкторов и функций.
Я импортировал класс C ++ в оболочке SWIG (Word. cpp), удалив несколько конструкторов, и у них есть только один значение по умолчанию
См. ниже:
#ifndef WORD_H
#define WORD_H
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
class Word {
public:
Word();
// REMOVED Word(std::string the_word);
//REMOVED Word(const Word& orig);
virtual ~Word();
virtual void updateWord(std::string word);
virtual std::string getWord();
private:
std::string _the_word;
};
#endif /* WORD_H */
SWIG-интерфейс для Word.h:
%{
/* Put header files here or function declarations like below */
/*#include "example.h"*/
#include "Word.h"
%}
%include "std_string.i"
/* %include "example.h"*/
%include "Word.h"
И использовались следующие параметры компиляции:
swig -python example.i
swig -python -c++ example.i
python setup.py build_ext --inplace
Python:
python
Python 2.7.5 (default, Aug 2 2016, 04:20:16)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import _example
_example.new_Word()
<Swig Object of type 'Word *' at 0x7f4debcceb70>
_example.new_Word()
swig/python detected a memory leak of type 'Word *', no destructor found.
<Swig Object of type 'Word *' at 0x7f4debcced50>
w = _example.new_Word()
_example.Word_updateWord(w,"beef")
_example.Word_getWord(w)
swig/python detected a memory leak of type 'Word *', no destructor found.
'beef'
_example.Word_updateWord(w,"chicken")
_example.Word_getWord(w)
'chicken'
Таким образом, без этой же функции или сигнатуры конструктора мы можем экспортировать класс C ++ в виде Python модуля.
Однако это очень ограниченно, так как шаблоны проектирования с ориентацией на объекты используют перегрузку / переопределение значительно.
Спасибо,
Миллион!