ImportError:使用 SWIG 时 _...so 文件中的未定义符号

Posted

技术标签:

【中文标题】ImportError:使用 SWIG 时 _...so 文件中的未定义符号【英文标题】:ImportError: undefined symbol in _...so file when using SWIG 【发布时间】:2019-02-19 11:55:22 【问题描述】:

我正在使用 SWIG 将 C++ 代码转换为 python 代码,但我没有成功解决以下导入错误。我无法知道问题的根源

ImportError: /.../_RfBm.so: 未定义符号:_ZN5RNormclERSt6vectorIdSaIdEE

RfBm.i 文件由下式给出

%module RfBm
%   
  #define SWIG_FILE_WITH_INIT
  #include "RfBm.h"
%
%include "RfBm.h"

.cpp文件由以下代码给出

#include "RfBm.h"

RfBm::RfBm() 
n = 0;
H = 0.0;
gamma = 0.0;
rnorm = 0;
L = std::vector<Vector>(0);


double RfBm::A(int i, int j) const 
double ret = 0.0;
if((i < n) && (j < n))
    ret = cBm(i,j);
else if((i < n) && (j >= n))
    ret = cMixed(i, j-n);
else if((i >= n) && (j < n))
    ret = cMixed(j, i-n);
else if((i >= n) && (j >= n))
    ret = cfBm(i-n, j-n);
return ret;


double RfBm::G(double x) const 
return 2.0 * H
        * (pow(x, -gamma) / (1.0 - gamma)
                + gamma * pow(x, -(1.0 + gamma))
                        * gsl_sf_hyperg_2F1(1.0, 1.0 + gamma, 3.0 - gamma,
                                1.0 / x) / ((1.0 - gamma) * (2.0 - gamma)));


double RfBm::cBm(int i, int j) const 
return (i == j) ? 1.0 : 0.0;


double RfBm::cfBm(int i, int j) const 
double t = static_cast<double>(std::min(i,j) + 1) / n;
double s = static_cast<double>(std::max(i,j) + 1) / n;
return pow(t, 2*H) * G(s/t);


double RfBm::cMixed(int i, int j) const 
double ret = 0.0;
if(i <= j)
    double u = static_cast<double>(i)/n;
    double v = static_cast<double>(i+1)/n;
    double t = static_cast<double>(j+1)/n;
    ret = 2.0 * sqrt(2.0*H*n) * (pow(t - u, 0.5 + H) - pow(t - v, 0.5 + H)) / 
(1.0 + 2.0 * H);

return ret;


RfBm::RfBm(int nI, double HI, RNorm* rnormI) 
n = nI;
H = HI;
gamma = 0.5 - H;
rnorm = rnormI;
L = std::vector<Vector>(2 * n, Vector(2 * n, 0.0)); // fill with 0s first.
// Now fill the matrix L.
for (int k = 0; k < 2 * n; ++k) 
    double temp = 0.0;
    for (int j = 0; j < k; ++j)
        temp += L[k][j] * L[k][j];
    L[k][k] = sqrt(A(k, k) - temp);
    for (int i = k + 1; i < 2*n; ++i) 
        double temp = 0.0;
        for (int j = 0; j < k; ++j)
            temp += L[i][j] * L[k][j];
        L[i][k] = (A(i, k) - temp) / L[k][k];
       
      


void RfBm::generate(Vector& W1, Vector& Wtilde) 
Vector x(2 * n);
(*rnorm)(x);
for (int i = 0; i < n; ++i) 
    W1[i] = 0.0;
    for (int j = 0; j <= i; ++j)
        W1[i] += L[i][j] * x[j];

for (int i = 0; i < n; ++i) 
    Wtilde[i] = 0.0;
    for (int j = 0; j <= (i + n); ++j)
        Wtilde[i] += L[i + n][j] * x[j];



void RfBm::operator ()(Vector& W1, Vector& Wtilde) 
this->generate(W1, Wtilde);


std::vector<Vector> RfBm::GetA() const 
std::vector<Vector> A_mat(2*n, Vector(2*n, 0.0));
for(int i=0; i<2*n; ++i)
    for(int j=0; j<2*n; ++j)
        A_mat[i][j] = A(i,j);
return A_mat;

我用于编译和链接的命令是:

swig -c++ -python RfBm.i
g++ -O2 -fPIC -c RfBm.cpp -I/home/.../gsl/include
g++ -O2 -fPIC -c RfBm_wrap.cxx  -I/home/.../gsl/include
g++ -shared -o _RfBm.so RfBm.o RfBm_wrap.o -L/home/.../gsl/lib -lgsl 
-lgslcblas -lm       

有什么帮助吗?谢谢。

【问题讨论】:

编译你的库以解决链接-Xlinker -z -Xlinker defs时丢失的符号。 What is an undefined reference/unresolved external symbol error and how do I fix it?的可能重复 我添加了 -Xlinker -z -Xlinker defs 但它说 g++: error: Xlinker: No such file or directory。另外我认为这不是重复的,因为我认为这里的问题与使用 SWIG 有关。我在问题中更新了我为编译和链接输入的命令。 我同意 OP 这不是重复的。特别是,这是一个 Python ImportError 【参考方案1】:

我发现了问题。事实上,首先我查看了 _ZN5RNormclERSt6vectorIdSaIdEE 的定义位置。它不在 RfBM.o 中,而是在另一个文件 RNorm.o 中

nm RfBm.o | grep _ZN5RNormclERSt6vectorIdSaIdEE

U _ZN5RNormclERSt6vectorIdSaIdEE

nm RNorm.o | grep _ZN5RNormclERSt6vectorIdSaIdEE

0000000000000280 T _ZN5RNormclERSt6vectorIdSaIdEE

然后我所做的就是在链接命令的末尾添加了那个文件

g++ -shared -o _RfBm.so RfBm.o  RfBm_wrap.o -L/home/.../gsl/lib -lgsl
-lgslcblas -lm RNorm.o

它解决了这个问题。

【讨论】:

以上是关于ImportError:使用 SWIG 时 _...so 文件中的未定义符号的主要内容,如果未能解决你的问题,请参考以下文章

SWIG + setup.py:ImportError:动态模块未定义初始化函数(init_foo)

SWIG - python 中的 C++ 代码

使用 SWIG 包装调用另一个对象成员函数的 C++ 类

如何使用 SWIG 为 C++ 类提供 Python __repr__()

SWIG 和 Python3 导入错误

ImportError:从 sklearn 导入 TfidfVectorizer 时无法导入名称 __check_build