SWIG Python 未定义符号错误
我正在尝试使用SWIG创建一个*.so文件,以便在Python中进一步使用,但遇到了一些问题。
我有两个文件:
DataGatherer.h
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include "gnublin.h"
#include <pthread.h>
class dataGatherer
{
private:
int threshold;
int timeThreshold;
int data[4096];
bool running;
gnublin_spi* spiDevice;
pthread_t spiThread;
void *params;
public:
dataGatherer(void);
dataGatherer(int, int);
void initData();
int getThreshold(void);
int* getData(void);
int getPeak(void);
void initSPI(void);
void gatherData();
void * run(void * arg);
void stop(void);
// for use of thread we have to implement some methods from C
static void * start_static(void * params)
{
dataGatherer * thread_this = static_cast<dataGatherer*>(params);
return thread_this->run(thread_this->params);
}
void start(void * params)
{
this->params = params;
pthread_create(&spiThread, 0, &dataGatherer::start_static, this);
}
};
和spiController.h
#include "dataGatherer.h"
class spiController
{
private:
bool runGather;
dataGatherer* gatherer;
int data[4096];
public:
spiController(void);
spiController(int, int);
void initData();
bool checkStop();
void stop();
void start();
};
我的spiController.i接口文件看起来是这样的:
/* spiController.i */
%module spiController
%{
#include "dataGatherer.h"
#include "spiController.h"
#include "gnublin.h"
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
extern void initData();
extern bool checkStop();
extern void stop();
extern void start();
%}
extern void initData();
extern bool checkStop();
extern void stop();
extern void start();
最后,我尝试使用终端中的命令来创建*.so文件,像SWIG页面上的示例一样:
swig -python -c++ spiController.i
c++ -c spiController_wrap.c -I/usr/include/python2.7
c++ -shared spiController_wrap.o -o _spiController.so
*.cxx、*.o和*.so文件都创建成功,没有错误,但当我在Python代码中导入spiController时,我得到了:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "spiController.py", line 26, in <module>
_spiController = swig_import_helper()
File "spiController.py", line 22, in swig_import_helper
_mod = imp.load_module('_spiController', fp, pathname, description)
ImportError: ./_spiController.so: undefined symbol: _Z9checkStopv
这是我第一次使用SWIG,现在卡在这里了。我该如何解决这个问题呢?
6 个回答
在我的情况下,我也遇到了那个错误,花了一些时间尝试各种方法但都没有成功。我的问题是,虽然我的源文件是普通的C语言,但我把它命名为.cpp
的扩展名,以为这没关系。把扩展名改成.c
后,问题就自动解决了。
另外一种解决方法是,在SWIG的.i
文件的头部添加这一行#include "example.cpp"
。
所以,总结一下:
example.c
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
example.i
%module example
%{
extern int fact(int n);
%}
extern int fact(int n);
然后在我的Ubuntu 17.10上,以下代码就能正常工作:
swig -c++ -python example.i
gcc -fPIC -c example.c example_wrap.c -I /usr/include/python2.7
gcc -shared example.o example_wrap.o -o _example.so
python -c "import example; print example.fact(5)"
希望这能帮助到某些人!
谢谢
虽然这个问题可能有很多原因,但我在用 Python 3.5 的头文件编译共享库时,遇到了完全相同的错误,比如:
swig -python example.i
gcc -fPIC -c example.c example_wrap.c -I/usr/include/python3.5 # <-- ISSUE HERE
gcc -shared example.o example_wrap.o -o _example.so
后来我尝试用 python test.py
来使用这个示例库,但系统上运行的是 Python 2.7(所以这是一个 Python 版本不匹配的问题)。
就像Adam的评论和我的经验一样,你首先需要把你的 XXX.cpp
文件编译成 XXX.o
文件,整个命令行可能像下面这样:
swig -python -c++ XXX.i
g++ -c -fpic XXX.cpp* (这个命令会生成 XXX.o 文件)
g++ -c -fpic XXX_wrap.cxx -I/usr/include/python2.7* (这个命令会生成 XXX_wrap.o 文件)
g++ -shared XXX.o XXX_wrap.o -o XXX.so
我刚遇到同样的错误,最后终于搞明白了原因。就像上面的人说的,当你看到“找不到符号”这样的提示,并且出现了未定义的函数名'_Z9checkStopv'时,一定要检查一下这个函数在.cpp文件中的实现情况,还有同名函数的声明!
在我的情况下,我的.cpp文件确实定义了那个“找不到符号”的构造函数,但在我的.h文件里,我有一个重载的赋值运算符(针对构造函数),这个在.cpp文件里没有实现。所以swig会把默认构造函数(在.cpp里实现的)和赋值运算符(没有实现的)都包装起来。因此在导入时,这个未实现的赋值运算符就会产生错误。希望这能帮到你!
你需要链接一个库,这个库里定义了你在代码中声明的C++函数,比如checkStop
等等。你需要在你示例的编译步骤的第三行添加-L<你的C++ DLL的路径> -l<你的C++ DLL的名字>
。
就像这样:
c++ -L<path to DLL> -l<name of your dll> -shared spiController_wrap.o -o _spiController.so