首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用gcc构建pybind11项目时获取未定义的引用

使用gcc构建pybind11项目时获取未定义的引用
EN

Stack Overflow用户
提问于 2020-04-06 16:46:53
回答 1查看 4.3K关注 0票数 2

我试图在Linux中构建一个C++静态库(在我的例子中是Ubuntu18.04),使用Makefile使用GCC。我注意到问题不在makefile本身,而是我试图与GCC一起编译和构建的方式。在我进一步解释GCC方面之前,下面是我当前的项目层次结构。

该项目只使用驻留在Pybind11目录中的External_Libraries标头库。

我的类定义和实现,命名Core.hCore.cpp与包含一些实用函数的py_utilities.hany.hpp一起驻留在Internal_libraries中。(这两个文件不使用)。最后,使用test_lib.cppCore.h驻留在根目录中。

这就是它的样子:

代码语言:javascript
运行
复制
MainDirectory  
 ┣ External_Libraries  
 ┃ ┗ Pybind11    
 ┃   ┗ Pybind11    
 ┃     ┗ Include      
 ┃ 
 ┣ Internal_Libraries  
 ┃ ┣Core.h  
 ┃ ┣Core.cpp  
 ┃ ┣py_utilities.h  
 ┃ ┣any.hpp  
 ┃
 ┗test_lib.cpp  

现在,正如您所看到的,这个项目依赖于Pybind11包含目录,也依赖于<Python.h> + pythons目录。在试图构建静态库或普通可执行文件时,我都会遇到相同的未定义错误。我包括GCC所需的搜索路径(包括和库)如下:

  • 构建Core.o
代码语言:javascript
运行
复制
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
代码语言:javascript
运行
复制
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可执行文件:
代码语言:javascript
运行
复制
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

这是它失败的地方,我得到了许多未定义的错误,我猜这些错误与链接器有关,但是我提供了所需的路径,所以我不知道哪里出了问题!

以下是我所犯的错误:

代码语言:javascript
运行
复制
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

下面是指向完整错误日志的链接:错误日志

如果Core.h的内容在这里很重要,则如下所示:

代码语言:javascript
运行
复制
#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上做同样的事情。很明显,我好像做错了什么,但我似乎不知道自己哪里出了问题。我在这里错过了什么?

更新

在手动编译链接之后,我完成了以下操作:

代码语言:javascript
运行
复制
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关键字,这样它就不会创建共享库了!尽管如此,最后一个命令仍然会导致链接器错误:

代码语言:javascript
运行
复制
 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。不过,我提供了Python,特别是libs目录,因此g++应该能够找到库并链接它们。我不明白为什么这不管用。这里少了什么?

我甚至创建了一个bash文件,并尝试了我找到的所有路径,但都没有结果:

代码语言:javascript
运行
复制
#!/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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-07 17:11:56

简短答覆:

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

代码语言:javascript
运行
复制
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目录,或者只需在终端中执行python3-config --ldflagspython3.7-config --ldflags (如果有多个安装,则取决于您版本的python )。(谢谢@ChrisD)。

但是,为了使可执行文件正确运行,lib文件夹需要位于PATH中,或者可以使用ldconfig加载所需的库。*我也必须这样做:

代码语言:javascript
运行
复制
sudo ldconfig /home/rika/anaconda3/lib/

附带说明:

我还发现本网站在链接过程中非常有用。我还试图直接使用图书馆,即:

代码语言:javascript
运行
复制
home/hossein/anaconda3/pkgs/python-3.7.4-h265db76_1/lib/libpython3.7m.a

这导致了错误:

代码语言:javascript
运行
复制
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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61064801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档