将 pybind11 与调用外部函数的动态库链接时出现未定义符号错误

2024-04-08

我正在尝试将 pybind11 模块与.so动态库,并且该库调用未在动态库中实现的函数.so文件。它在普通的 C++ 可执行文件中工作正常,但会引发Undefined Symbolpython导入时出错。

这是一个简单的演示来重现我的问题。

功能Student::print()被编译成动态库并调用函数Student::setId()不包括在.so文件。 (如果使用nm命令,它会显示U _ZN7Student5setIdEi.)

它工作得很好main.cpp打电话Student::print(), 但在test.py,它提出ImportError: {mypath}/libstu_lib.so: undefined symbol: _ZN7Student5setIdEi

为了简化,我将外部函数设置为它自己的成员函数。当调用属于另一个类的函数时,问题仍然会重现,所以我认为这并不重要。

pybind11 有没有选项可以解决这个问题?因为动态库的源代码很难修改。谢谢。

学生.h

#include <iostream>
using namespace std;

class Student {
    public:
        Student(int id);
        void setId(int id);
        void print();
    private:
        int id;
};

学生.cpp

#include "Student.h"

Student::Student(int id) {
    this->id = id;
}

void Student::setId(int id) {
    this->id = id;
}

学生库.cpp

#include "Student.h"

void Student::print() {
    cout << "id: " << this->id << endl;
    this->setId(111);
    cout << "id: " << this->id << endl;
}

Student_wrapper.cpp

#include <pybind11/pybind11.h>
#include "Student.h"

namespace py = pybind11;

PYBIND11_MODULE(stu, m){
    py::class_<Student>(m, "Student")
        .def(py::init<int>())
        .def("setId", &Student::setId)
        .def("print", &Student::print);
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(test)

link_directories(${PROJECT_SOURCE_DIR})

add_library(stu_lib SHARED Student_lib.cpp)

add_executable(main main.cpp Student.cpp)
target_link_libraries(main stu_lib)

find_package(pybind11 REQUIRED)
pybind11_add_module(stu Student_wrapper.cpp Student.cpp)
target_link_libraries(stu PUBLIC stu_lib)

main.cpp

#include "Student.h"

int main(int argc, char** argv) {
    Student* s = new Student(1);
    s->print();
    return 0;
}

test.py

from stu import Student

s = Student(1)
s.print()

输出ldd libstu_core.so:

        linux-vdso.so.1 (0x00007ffcffdac000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f3def395000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3def1a3000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3def054000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3def593000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3def039000)

老实说:我不知道 pybind11 内部的工作原理足以告诉你why这正在发生。但是,有一种解决方法可以使您的代码正常工作,那就是编译Student.cpp到它自己的共享库中并将其链接到 pybind11 模块。这是您可以修改您的CMakeLists.txt使其发挥作用:

cmake_minimum_required(VERSION 3.15)
project(test)

link_directories(${PROJECT_SOURCE_DIR})

add_library(stu_lib SHARED Student_lib.cpp)

add_executable(main main.cpp Student.cpp)
target_link_libraries(main stu_lib)

find_package(pybind11 REQUIRED)
add_library(stu_class SHARED Student.cpp)
pybind11_add_module(stu Student_wrapper.cpp)
target_link_libraries(stu PUBLIC stu_lib stu_class)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 pybind11 与调用外部函数的动态库链接时出现未定义符号错误 的相关文章

随机推荐