编译引用另一个预编译库的库后出现Missing symbol错误

问题描述 投票:0回答:0

tl;dr:我正在尝试编译一个引用另一个已编译 API(.so + .h 文件)的 .cpp 文件,但在尝试加载它时我得到了一个丢失的符号。下面是一个简单的示例,说明我如何创建模块,以及我在此过程中执行的所有步骤。帮助将不胜感激。

注意: 在你决定跳过这个问题之前,因为你可能对 Cython 一无所知,这更像是一个链接器/g++ 问题而不是一个 cython 问题,所以请读到最后。

我正在尝试创建一个包含预编译 C++ API 库的 Cython 模块,但在导入到 Python 时出现奇怪的错误。所以我做了一个简单的例子,期间:

  1. 编译一个简单的 C++ 库(.so + .h 文件)
  2. 编译一个引用它的简单 Cython 模块。
  3. 在 Python 中加载该模块以访问底层 C++ 库。

首先我有以下两个文件:

// circle.h
#ifndef CIRCLE_H
#define CIRCLE_H

class Circle {
public:
    Circle(float radius);
    float getDiameter() const;

private:
    float m_radius;
};

#endif // CIRCLE_H

//circle.cpp
#include "circle.h"

Circle::Circle(float radius) : m_radius(radius) {}

float Circle::getDiameter() const {
    return m_radius * 2.0f;
}

我使用以下命令将这些编译成

build/Circle.so

mkdir -p build
g++ -O2 -fPIC -c circle.cpp -o build/Circle.o
g++ -shared build/Circle.o -o build/Circle.so
cp circle.h build/Circle.h

现在我转而创建我的 Cython 模块,方法是创建以下名为

example.pyx
的文件:

# distutils: language = c++

cdef extern from "build/Circle.h":
    cdef cppclass Circle:
        Circle(float radius)
        float getDiameter()

cdef class PyCircle:
    cdef Circle* c_circle

    def __cinit__(self, float radius):
        self.c_circle = new Circle(radius)

    def __dealloc__(self):
        del self.c_circle

    def getDiameter(self):
        return self.c_circle.getDiameter()

然后我运行

cythonize -i example.pyx
并在根目录中得到两个文件:
example.cpp
(Cython生成的源文件)和
example.cpython-39-x86_64-linux-gnu.so
。我将后者重命名为
example.so
并尝试从 python (
import example
) 导入它,但出现以下错误:

导入错误:example.cpython-39-x86_64-linux-gnu.so:未定义符号:_ZNK6Circle11getDiameterEv

所以我使用命令

Circle.so
查看了预先编译的(几乎是一个词)模块
nm -D build/Circle.so | grep Diameter
,实际上我看到丢失的符号位于该模块中:

0000000000001110 T _ZNK6Circle11getDiameterEv

所以我想“链接器一定有问题。我知道!让我们编译自动生成的 .cpp 源代码并链接到那个库!”。所以我做了以下事情:

  1. g++ -O2 -fPIC -c example.cpp -I /usr/include/python3.9 -I build/Circle.h
  2. 重命名
    build/Circle.so
    libCircle.so
  3. g++ -shared example.o -Lbuild -lCircle -o example.so
  4. 在 python 控制台中运行
    import example
    ,我得到了同样的错误。

我做错了什么?为什么那个符号没有加载?

python c++ linker g++ cython
© www.soinside.com 2019 - 2024. All rights reserved.