我想在一个大型c++项目上添加一个简单的python接口,以便我可以使用python调用一些c++函数。这是一个大型的c++项目,结构如下
FastBN
-src
// many source files inside
-include
// many header files inside
-lib
CMakeLists.txt
对于我的第一次尝试,我刚刚在
include
中创建了一个新的头文件,在 src
中创建了一个源文件:
// test.h
extern "C" {
int add(int n1, int n2);
}
// test.cpp
#include "test.h"
int add(int n1, int n2) {
return n1 + n2;
}
构建后,我生成了
libfastbn.so
。然后我尝试了一个简单的 python 脚本:
import ctypes
mylib = ctypes.CDLL('./libfastbn.so')
mylib.add.argtypes = [ctypes.c_int, ctypes.c_int]
mylib.add.restype = ctypes.c_int
v1= 32
v2= 121
c = mylib.add(v1, v2)
print(c)
但是运行python脚本时出现以下错误。
Traceback (most recent call last):
File "/home/jjt/work/BN/FastBN/build/python_interface.py", line 3, in <module>
mylib = ctypes.CDLL('./libfastbn.so')
File "/home/jjt/anaconda3/lib/python3.9/ctypes/__init__.py", line 382, in __init__
self._handle = _dlopen(self._name, mode)
OSError: ./libfastbn.so: undefined symbol: _ZNK8tinyxml27XMLNode17FirstChildElementEPKc
.so
文件是通过CMakeLists.txt生成的,我也在下面附上了它。然而,这是针对整个 C++ 项目的。
cmake_minimum_required(VERSION 3.10)
project(BayesianNetwork)
add_definitions("-Wall -g")
set(CMAKE_CXX_STANDARD 14)
#set(CMAKE_CXX_FLAGS_RELEASE "-O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
option(USE_MPI "option for mpi" OFF)
if (USE_MPI)
message("Use MPI")
add_definitions(-DUSE_MPI)
find_package(MPI REQUIRED)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
endif ()
include_directories(${PROJECT_SOURCE_DIR}/lib/tinyxml2)
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_SOURCE_DIR}/lib/ARFF/src)
include_directories(${PROJECT_SOURCE_DIR}/lib/stats/include)
include_directories(${PROJECT_SOURCE_DIR}/lib/gcem/include)
add_subdirectory(lib)
add_subdirectory(src/fastbn)
add_subdirectory(src/test)
file(GLOB_RECURSE SRC src/fastbn/*.cpp)
file(GLOB HEAD include/*.h)
add_library(fastbn SHARED ${SRC} ${HEAD})
add_executable(BayesianNetwork ${SRC} ${HEAD})
target_link_libraries(BayesianNetwork tinyxml2 ARFF stats gcem)
target_link_libraries(BayesianNetwork ${MPI_C_LIBRARIES})
使用 ctypes 返回的未定义符号错误可能是加载程序失败的结果。
建议对非标准位置的库使用绝对路径,相对路径可能有效也可能无效,具体取决于操作系统品牌。
import ctypes;
import pathlib;
mylib_path = pathlib.Path(__file__).absolute() / "libfastbn.so"
mylib = ctypes.CDLL(mylib_path)
至于加载每个库,如果所有依赖项都位于标准位置或 LD_LIBRARY_PATH,则无需重新实现动态链接器功能,您可能需要使用 LD_DEBUG 进行诊断:https://tldp.org/HOWTO/程序库-HOWTO/shared-libraries.html#AEN77