SWIG Python未定义符号错误

4

我正在尝试使用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);
    }

};

and 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文件已经创建,没有错误,但是当我将spiController导入到Python代码中时,出现了以下问题:

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,但我已经卡在这个点上了。我该如何解决这个问题?


1
_Z9checkStopv是checkstop函数的名称修饰符。该函数是否已定义? - Beed
1
你从未提及实际包含函数体的 .cpp 文件。这些文件也必须链接到你的 .so 文件中。 - Adam
6个回答

5
我刚刚遇到了相同的错误,最终找出了原因。如上所述,当它说像你这样的未发现符号并给出未定义的函数名“_Z9checkStopv”时,请始终检查.cpp文件中此函数的实现以及相同名称的任何函数声明!
对于我的情况,我的cpp确实定义了我的“未发现符号”构造函数,但在我的.h文件中,我有一个重载的operator=(用于构造函数),该operator=在.cpp文件中未定义。因此,swig包装了默认构造函数(在.cpp中实现)和operator=(未实现)。因此,在导入时,这个未实现的operator=会产生错误。希望这可以帮助!

3

正如Adam的评论和我的经验一样,你应该首先将XXX.cpp文件编译成XXX.o文件,整个命令行可能像以下这样:

  1. swig -python -c++ XXX.i

  2. g++ -c -fpic XXX.cpp* (此命令将生成XXX.o文件)

  3. g++ -c -fpic XXX_wrap.cxx -I/usr/include/python2.7* (此命令将生成XXX_wrap.o文件)

  4. g++ -shared XXX.o XXX_wrap.o -o XXX.so


3

你必须链接包含你已声明的 C++ 函数(例如 checkStop)的库。在编译示例时,你需要在第三行添加 -L<C++动态链接库路径> -l<C++动态链接库名称>

像这样:

c++ -L<path to DLL> -l<name of your dll> -shared spiController_wrap.o -o _spiController.so

不行,这并没有解决问题。 - John Greene

2
尽管这个问题可能有很多原因,但当我使用Python v3.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 v2.7(因此是Python版本不匹配的问题)。


0

我知道解决方案。在编译共享库的最后,你应该使用 g++ -shared -fpic *.o *.o -o _***.so


  1. swig -python -c++ example.i
  2. g++ -c -fpic example.cpp
  3. g++ -c -fpic example_wrap.cxx -I/usr/include/python3.5
  4. g++ -shared -fpic example_wrap.o example.o -o _examplejava.so 下一步是使用:python3
- wei wang

0
在我的情况下,我也遇到了这个错误,并花了一些时间尝试各种方法,但都没有成功。我的问题是,尽管我的源文件是纯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)"

希望这能帮助到某个人!
干杯


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接