c++ - 尝试使用gcc构建pybind11项目时获取 undefined reference

标签 c++ g++ python-c-api pybind11

我正在尝试使用Makefile使用GCC在Linux中构建C++静态库(在我的情况下为Ubuntu 18.04)。我注意到问题不在于makefile本身,而是我尝试使用GCC进行编译和构建的方式。在我对GCC进行更多解释之前,这是我当前项目层次结构的样子。
该项目仅使用位于Pybind11目录中的External_Libraries header 库。
我的类定义和实现,命名Core.hCore.cpp以及包含一些实用程序功能的Internal_librariespy_utilities.h都驻留在any.hpp中。 (尽管这两个文件未使用)。最后使用test_lib.cppCore.h驻留在根目录中。
看起来是这样的:

📦MainDirectory  
 ┣ 📂External_Libraries  
 ┃ ┗ 📂Pybind11    
 ┃   ┗ 📂Pybind11    
 ┃     ┗ 📂Include      
 ┃ 
 ┣ 📂Internal_Libraries  
 ┃ ┣📜Core.h  
 ┃ ┣📜Core.cpp  
 ┃ ┣📜py_utilities.h  
 ┃ ┣📜any.hpp  
 ┃
 ┗📜test_lib.cpp  
现在,如您所见,该项目取决于Pybind11包含目录以及<Python.h>加上pythons lib目录。当我尝试构建静态库或普通可执行文件时,我都遇到相同的未定义错误。我将所需的搜索路径(包括和库)包括到GCC中,如下所示:
  • 建筑Core.o:

  • g++ -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages -c ./Internal_Libraries/Core.cpp -o Core.o
    
  • 建筑test_lib.o:

  • g++ -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages -c test_lib.cpp -o test_lib.o
    
    最后:
  • 构建test_lib可执行文件:

  • g++ -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages test_lib.o Core.o -o test_lib
    
    这是失败的地方,我收到许多未定义的错误,我猜想与链接器有关,但是我提供了所需的路径,所以我很茫然这里出了什么问题!
    这些是我得到的错误:
    g++ -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages test_lib.o Core.o -o test_lib
    test_lib.o: In function `pybind11::cast_error::set_error() const':
    test_lib.cpp:(.text._ZNK8pybind1110cast_error9set_errorEv[_ZNK8pybind1110cast_error9set_errorEv]+0x29): undefined reference to `PyExc_RuntimeError'
    test_lib.cpp:(.text._ZNK8pybind1110cast_error9set_errorEv[_ZNK8pybind1110cast_error9set_errorEv]+0x34): undefined reference to `PyErr_SetString'
    test_lib.o: In function `pybind11::error_scope::error_scope()':
    test_lib.cpp:(.text._ZN8pybind1111error_scopeC2Ev[_ZN8pybind1111error_scopeC5Ev]+0x27): undefined reference to `PyErr_Fetch'
    test_lib.o: In function `pybind11::error_scope::~error_scope()':
    
    ...
    
    Core.o: In function `std::enable_if<((!std::is_floating_point<int>::value)&&std::is_signed<int>::value)&&((sizeof (int))<=(sizeof (long))), pybind11::handle>::type pybind11::detail::type_caster<int, void>::cast<int>(int, pybind11::return_value_policy, pybind11::handle)':
    Core.cpp:(.text._ZN8pybind116detail11type_casterIivE4castIiEENSt9enable_ifIXaaaantsrSt17is_floating_pointIT_E5valuesrSt9is_signedIS6_E5valuelestS6_stlENS_6handleEE4typeES6_NS_19return_value_policyESA_[_ZN8pybind116detail11type_casterIivE4castIiEENSt9enable_ifIXaaaantsrSt17is_floating_pointIT_E5valuesrSt9is_signedIS6_E5valuelestS6_stlENS_6handleEE4typeES6_NS_19return_value_policyESA_]+0x2c): undefined reference to `PyLong_FromSsize_t'
    Core.o: In function `pybind11::array_t<unsigned char, 16>::ensure(pybind11::handle)':
    Core.cpp:(.text._ZN8pybind117array_tIhLi16EE6ensureENS_6handleE[_ZN8pybind117array_tIhLi16EE6ensureENS_6handleE]+0x70): undefined reference to `PyErr_Clear'
    Core.o: In function `pybind11::array_t<unsigned char, 16>::raw_array_t(_object*)':
    Core.cpp:(.text._ZN8pybind117array_tIhLi16EE11raw_array_tEP7_object[_ZN8pybind117array_tIhLi16EE11raw_array_tEP7_object]+0x26): undefined reference to `PyExc_ValueError'
    Core.cpp:(.text._ZN8pybind117array_tIhLi16EE11raw_array_tEP7_object[_ZN8pybind117array_tIhLi16EE11raw_array_tEP7_object]+0x35): undefined reference to `PyErr_SetString'
    collect2: error: ld returned 1 exit status
    
    这是完整错误日志的链接:error log
    如果Core.h的内容很重要,这里是:
    #ifndef CORE_H
    
    #define CORE_H
    
    
    
    /* If we are we on Windows, we want a single define for it.*/
    
    #if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
    
     #define _WIN32
    
    #endif /* _WIN32 */
    
    
    #if defined(_WIN32) && defined(_CORE_BUILD_DLL)
    
    /* We are building CORE as a Win32 DLL */
    
     #define CORE_API __declspec(dllexport)
    
    #elif defined(_WIN32) && defined(CORE_DLL)
    
    /* We are calling CORE as a Win32 DLL */
    
     #define CORE_API __declspec(dllimport)
    
    #elif defined(__GNUC__) && defined(_CORE_BUILD_DLL)
    
    /* We are building CORE as a shared / dynamic library */
    
    #define CORE_API __attribute__((visibility("default")))
    
    #else
    
    /* We are building or calling CORE as a static library */
    
     #define CORE_API
    
    #endif
    
    
    #include <iostream>
    #include <string>
    #include <vector>
    #include <functional>
    #include <memory>
    #include <pybind11/pybind11.h>
    #include <pybind11/embed.h>
    #include <pybind11/numpy.h>
    #include <pybind11/stl.h>
    #include <pybind11/functional.h>
    
    namespace py = pybind11;
    using namespace py::literals;
    
    typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
    typedef std::function<void(std::string)> LogFunction;
    typedef void * HANDLE;
    
    
    class CORE_API Core
    
    {
    private:
        py::scoped_interpreter guard{};
        py::object serviceUtilsModule;
        py::object cls;
        py::object obj;
        py::object startFunc;
    ...
    
    
    
    public:
    
        Core();
        Core(bool showFeed);
        Core(LogFunction logInfo);
        Core(LogFunction logInfo, LogFunction logWarning);
        Core(LogFunction logInfo, LogFunction logWarning, LogFunction logDebug);
        Core(LogFunction logInfo, LogFunction logWarning, LogFunction logDebug, std::vector<CallbackFn> callbackList);
    ...
        ~Core();
    
    
        void Start(bool async= false);
        py::list GetCallbacks(void);
    ...
        static void DefaultLoger(std::string str);
    };
    
    
    
    extern "C"
    
    {
        //COREAPI wchar_t** GetResults(wchar_t* word, int* length, int threshold = 9);
        CORE_API void Start(bool);
        CORE_API void Stop(void);
        CORE_API void SetCpuAffinity(int mask);
        CORE_API void AddCallback(CallbackFn callback);
        CORE_API void RemoveCallback(CallbackFn callback);
        CORE_API void* GetCallbacks(void);
        CORE_API void DefaultLoger(char* str);
    
        CORE_API void*  CreateHandle();
        CORE_API void*  GetCurrentHandle();
        CORE_API void   DisposeCurrentHandle();
        CORE_API void   SetCurrentHandle(void* handle);
        CORE_API void*  GetHandle();
        CORE_API void   DisposeHandle(void*);
    
    }
    
    
    
    #endif // !CORE_H
    
    该项目在Windows和Visual C++ v14(VS2015)下运行良好,现在我正在尝试使用GCC在Linux中执行相同的操作。看来我显然做错了什么,但我似乎不知道自己哪里出了问题。我在这里想念什么?
    更新资料
    在手动编译pybind11之后遵循此link之后,我最终做了:
    g++ -O3 -Wall -std=c++11 -fPIC -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages -c ./Internal_Libraries/Core.cpp -o Core.o
    g++ -O3 -Wall -std=c++11 -fPIC -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages -c test_lib.cpp -o test_lib.o
    g++ -O3 -Wall -std=c++11 -fPIC -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages test_lib.o Core.o -o test_lib
    
    请注意,我从上面的命令中删除了shared关键字,因此它不会创建共享库!说了最后一个命令仍然会给出链接器错误:
     g++ -O3 -Wall -std=c++11 -fPIC -I./External_Libraries/pybind11/pybind11/include -I/home/rika/anaconda3/include/python3.7m -L/home/rika/anaconda3/lib -L/home/rika/anaconda3/lib/python3.7/site-packages test_lib.o -o test_lib
    test_lib.o: In function `pybind11_static_get':
    test_lib.cpp:(.text.pybind11_static_get[pybind11_static_get]+0x3): undefined reference to `PyProperty_Type'
    test_lib.o: In function `pybind11_static_set':
    test_lib.cpp:(.text.pybind11_static_set[pybind11_static_set]+0x12): undefined reference to `PyProperty_Type'
    test_lib.o: In function `pybind11::cast_error::set_error() const':
    test_lib.cpp:(.text._ZNK8pybind1110cast_error9set_errorEv[_ZNK8pybind1110cast_error9set_errorEv]+0x10): undefined reference to `PyExc_RuntimeError'
    test_lib.cpp:(.text._ZNK8pybind1110cast_error9set_errorEv[_ZNK8pybind1110cast_error9set_errorEv]+0x1c): undefined reference to `PyErr_SetString'
    test_lib.o: In function `pybind11::detail::translate_exception(std::__exception_ptr::exception_ptr)':
    
    ...
    
    
    test_lib.cpp:(.text._ZN8pybind116detail5printENS_5tupleENS_4dictE[_ZN8pybind116detail5printENS_5tupleENS_4dictE]+0x9a): undefined reference to `PyTuple_Size'
    test_lib.cpp:(.text._ZN8pybind116detail5printENS_5tupleENS_4dictE[_ZN8pybind116detail5printENS_5tupleENS_4dictE]+0xaa): undefined reference to `PyTuple_GetItem'
    test_lib.cpp:(.text._ZN8pybind116detail5printENS_5tupleENS_4dictE[_ZN8pybind116detail5printENS_5tupleENS_4dictE]+0xd3): undefined reference to `PyObject_Str'
    test_lib.cpp:(.text._ZN8pybind116detail5printENS_5tupleENS_4dictE[_ZN8pybind116detail5printENS_5tupleENS_4dictE]+0x1cc): undefined reference to `PyDict_Contains'
    test_lib.cpp:(.text._ZN8pybind116detail5printENS_5tupleENS_4dictE[_ZN8pybind116detail5printENS_5tupleENS_4dictE]+0x3c1): undefined reference to `PyDict_Contains'
    test_lib.cpp:(.text._ZN8pybind116detail5printENS_5tupleENS_4dictE[_ZN8pybind116detail5printENS_5tupleENS_4dictE]+0x518): undefined reference to `PyImport_ImportModule'
    test_lib.o: In function `void pybind11::print<(pybind11::return_value_policy)1, pybind11::list>(pybind11::list&&)':
    test_lib.cpp:(.text._ZN8pybind115printILNS_19return_value_policyE1EJNS_4listEEEEvDpOT0_[_ZN8pybind115printILNS_19return_value_policyE1EJNS_4listEEEEvDpOT0_]+0x21): undefined reference to `PyDict_New'
    test_lib.o: In function `main':
    test_lib.cpp:(.text.startup+0x34): undefined reference to `Core::Core(bool)'
    test_lib.cpp:(.text.startup+0x41): undefined reference to `Core::SetCpuAffinity(int)'
    test_lib.cpp:(.text.startup+0x4b): undefined reference to `Core::Start(bool)'
    test_lib.cpp:(.text.startup+0x5b): undefined reference to `Core::GetCallbacks()'
    test_lib.cpp:(.text.startup+0x85): undefined reference to `Core::GetCallbacks()'
    test_lib.cpp:(.text.startup+0x107): undefined reference to `PyObject_Str'
    collect2: error: ld returned 1 exit status
    
    
    更新2
    查看错误,在我看来,问题不在于pybind11本身,而是 Python库PyObject_StrPyObject_StrPyImport_ImportModulePyProperty_Type等都是Python C API。但是我提供的是Python include,尤其是libs目录,因此g++应该能够找到这些libs并将它们链接起来。我不知所措,为什么这不起作用。这里缺少什么?
    我什至制作了一个bash文件,并尝试了所有找不到的路径:
    #!/bin/bash  
    
    PYBIND_INCL_DIR=-I/home/rika/Documents/cpp/External_Libraries/pybind11/pybind11/include
    PYTHON_INCL_DIR=-I/home/rika/anaconda3/include/python3.7m
    PYTHON_INCL_DIR2=-I/home/rika/anaconda3/pkgs/python-3.7.4-h265db76_1/include/python3.7m
    
    PYTHON_LIB_DIRS=-L/home/rika/anaconda3/lib/
    PYTHON_LIB_DIRS2=-L/home/rika/anaconda3/lib/python3.7/site-packages/
    PYTHON_LIB_DIRS3=-L/home/rika/anaconda3/pkgs/python-3.7.4-h265db76_1/lib/
    
    # echo $PYBIND_INCL_DIR
    # echo $PYTHON_INCL_DIR
    
    g++ $PYBIND_INCL_DIR  $PYTHON_INCL_DIR  $PYTHON_LIB_DIRS $PYTHON_LIB_DIRS2 $PYTHON_LIB_DIRS3 -c Core.cpp -o Core.o
    g++ $PYBIND_INCL_DIR  $PYTHON_INCL_DIR  $PYTHON_LIB_DIRS $PYTHON_LIB_DIRS2 $PYTHON_LIB_DIRS3 test_lib.cpp Core.o -o test_lib
    

    最佳答案

    简短答案:
    正如我所说,链接器错误与找不到Python库有关。为了获得成功的构建,只需要包含该库就可以了,因此最终的构建命令将是:

    PYBIND_INCL_DIR=-I/home/rika/Documents/mahsan_FV/cpp/External_Libraries/pybind11/pybind11/include
    PYTHON_INCL_DIR=-I/home/rika/anaconda3/include/python3.7m
    PYTHON_LIB_DIRS=-L/home/rika/anaconda3/lib/
    
    g++ $PYBIND_INCL_DIR  $PYTHON_INCL_DIR  $PYTHON_LIB_DIRS -c Core.cpp -o Core.o 
    g++ $PYBIND_INCL_DIR  $PYTHON_INCL_DIR  $PYTHON_LIB_DIRS test_lib.cpp Core.o -lpython3.7m -o test_lib
    

    只需将所有目标文件编译并链接在一起即可解决问题。

    更多说明:

    您可以通过导航到Python lib目录或简单地获取它
    在终端中执行python3-config --ldflagspython3.7-config --ldflags(取决于python版本,如果您有多个安装的话)。(谢谢@ ChrisD)

    但是,为了使可执行文件正常运行,lib文件夹必须位于PATH中,或者也可以使用ldconfig加载所需的库。 :
    我还必须做:
    sudo ldconfig /home/rika/anaconda3/lib/
    

    边注:
    我还发现this website对链接过程非常有帮助。
    我还尝试直接使用该库:

    home/hossein/anaconda3/pkgs/python-3.7.4-h265db76_1/lib/libpython3.7m.a
    

    导致错误:

    lto1: fatal error: bytecode stream in file ‘/home/rika/anaconda3/pkgs/python-3.7.4-h265db76_1/lib/libpython3.7m.a’ generated with LTO version 6.0 instead of the expected 6.2
    compilation terminated.
    lto-wrapper: fatal error: g++ returned 1 exit status
    

    证明获得正确链接的唯一方法是使用-lpython3.7m!

    关于c++ - 尝试使用gcc构建pybind11项目时获取 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61064801/

    相关文章:

    c++ - 如何在 C++ 中使用哈希在同一个键下存储多个值

    c++ - 使用 gcc 的 -fno-math-errno 可能产生哪些副作用?

    c++ - 为什么我的类(class)没有链接?

    c++ - g++ 无法找到此方法,即使它包含在内

    python - 第二次调用时无法从python模块获取该函数

    python - 编译多个模块时 import_array() 出现 Numpy/CAPI 错误

    c++ - 难以理解 * 和 & 当它们与线程一起出现时

    c++ - (a==1)&&(a==2)&&(a==3) 可以计算为真吗? (它有用吗?)

    c++ - 关闭父级以调用隐藏或显式关闭时消息框未关闭

    python - 尝试写入 C 扩展中创建的 Numpy 数组时出现 SegFault