尝试使用 gcc 构建 pybind11 项目时获取未定义的引用
Getting undefined reference when trying to build a pybind11 project using gcc
我正在尝试使用 GCC 使用 Makefile
在 Linux(在我的例子中是 Ubuntu 18.04)中构建一个 C++ 静态库。我注意到问题不在于 makefile 本身,而在于我尝试使用 GCC 进行编译和构建的方式。在我对 GCC 方面进行更多解释之前,这是我当前项目层次结构的样子。
该项目仅使用 Pybind11
header 位于 External_Libraries
目录中的库。
我的 class 定义和实现,命名 Core.h
和 Core.cpp
与 py_utilities.h
和 any.hpp
一起驻留在 Internal_libraries
中,其中包含一些效用函数。 (虽然这两个文件没有被使用)。最后使用 Core.h
的 test_lib.cpp
驻留在根目录中。
它是这样的:
MainDirectory
┣ External_Libraries
┃ ┗ Pybind11
┃ ┗ Pybind11
┃ ┗ Include
┃
┣ Internal_Libraries
┃ ┣Core.h
┃ ┣Core.cpp
┃ ┣py_utilities.h
┃ ┣any.hpp
┃
┗test_lib.cpp
现在,如您所见,该项目依赖于 Pybind11
include 目录以及 <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
这是它失败的地方,我收到很多未定义的错误,我猜这些错误与 linker 有关,但是我提供了所需的路径,所以我不知道这里出了什么问题!
这些是我得到的错误:
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
这里是 link 完整的错误日志: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
关键字,因此它不会创建共享库!话虽如此,最后一条命令仍然给出 linker 错误:
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_Str
、PyObject_Str
、PyImport_ImportModule
、PyProperty_Type
等都是 Python C API。但是我提供了 Python 包含,尤其是 libs 目录,所以 g++ 应该能够找到这些库和 link 它们。我不知道为什么这不起作用。这里缺少什么?
我什至制作了一个 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 --ldflags
或 python3.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
!
我正在尝试使用 GCC 使用 Makefile
在 Linux(在我的例子中是 Ubuntu 18.04)中构建一个 C++ 静态库。我注意到问题不在于 makefile 本身,而在于我尝试使用 GCC 进行编译和构建的方式。在我对 GCC 方面进行更多解释之前,这是我当前项目层次结构的样子。
该项目仅使用 Pybind11
header 位于 External_Libraries
目录中的库。
我的 class 定义和实现,命名 Core.h
和 Core.cpp
与 py_utilities.h
和 any.hpp
一起驻留在 Internal_libraries
中,其中包含一些效用函数。 (虽然这两个文件没有被使用)。最后使用 Core.h
的 test_lib.cpp
驻留在根目录中。
它是这样的:
MainDirectory
┣ External_Libraries
┃ ┗ Pybind11
┃ ┗ Pybind11
┃ ┗ Include
┃
┣ Internal_Libraries
┃ ┣Core.h
┃ ┣Core.cpp
┃ ┣py_utilities.h
┃ ┣any.hpp
┃
┗test_lib.cpp
现在,如您所见,该项目依赖于 Pybind11
include 目录以及 <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
这是它失败的地方,我收到很多未定义的错误,我猜这些错误与 linker 有关,但是我提供了所需的路径,所以我不知道这里出了什么问题!
这些是我得到的错误:
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
这里是 link 完整的错误日志: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
关键字,因此它不会创建共享库!话虽如此,最后一条命令仍然给出 linker 错误:
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_Str
、PyObject_Str
、PyImport_ImportModule
、PyProperty_Type
等都是 Python C API。但是我提供了 Python 包含,尤其是 libs 目录,所以 g++ 应该能够找到这些库和 link 它们。我不知道为什么这不起作用。这里缺少什么?
我什至制作了一个 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 --ldflags
或 python3.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
!