Python 从单个.cpp构建共享对象
我试图从一个简单的函数集Python 从单个.cpp构建共享对象,python,c++,shared-libraries,Python,C++,Shared Libraries,我试图从一个简单的函数集cpp文件构建一个共享对象库。我想使用ctypes与python进行接口 假设我有cpp文件: #include "print.h" #include <vector> #include <iostream> #include <dlfcn.h> void print_array(const std::vector<std::vector<float>> &A){ for(size_t i = 0;
cpp
文件构建一个共享对象库。我想使用ctypes
与python进行接口
假设我有cpp
文件:
#include "print.h"
#include <vector>
#include <iostream>
#include <dlfcn.h>
void print_array(const std::vector<std::vector<float>> &A){
for(size_t i = 0; i < A.size(); i++) {
for(size_t j = 0; j < A[0].size(); j++) {
std::cout << A[i][j] << "\n";
}
}
}
然后在python中
from cytpes import cdll
print_lib = cdll.LoadLibrary("print.so")
线路
print_lib.print_array()
屈服
AttributeError: ./print.so: undefined symbol: print_array
nm-D打印。因此
给出输出
0000000000201060 B __bss_start
U __cxa_atexit
w __cxa_finalize
0000000000201060 D _edata
0000000000201068 B _end
0000000000000c14 T _fini
w __gmon_start__
0000000000000898 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
0000000000000a50 T _Z11print_arrayRKSt6vectorIS_IfSaIfEESaIS1_EE
0000000000000bcc W _ZNKSt6vectorIfSaIfEE4sizeEv
0000000000000bf2 W _ZNKSt6vectorIfSaIfEEixEm
0000000000000b6a W _ZNKSt6vectorIS_IfSaIfEESaIS1_EE4sizeEv
0000000000000ba2 W _ZNKSt6vectorIS_IfSaIfEESaIS1_EEixEm
U _ZNSolsEf
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
我在编译步骤中到底做了什么? 你调用C++函数,而<代码> cType < /Cube >期待C函数链接:
- 正如您所注意到的,C函数有一个不同的名称mangling(即none)
为了解决您的问题,在您的头中声明一个干净的C风格API,如果您打算在C++中实现函数并使用g++作为编译器/链接器,则必须在标题文件中的函数声明之前添加一个<代码>外部“C”<代码>声明,或者作为声明的一个块:
extern "C" void print_array(...);
这将阻止C++名称的修改。
使用接口函数中的向量和其他C++类型会导致ABI问题。E“它不会工作”,即使所有的链接和编译看起来都很干净
使用C++函数,将函数中的cType(参见)支持的数据类型作为接口,在C++中实现,但在“代码”>“外部”“C”<代码>块中,将C函数声明包起来,以防止名称的篡改。
请参考cType的文档,以了解如何正确地使用结构、联合、引用等作为函数参数,因为有许多陷阱和问题需要考虑。
< p>您调用C++函数,而<代码> cType < /代码>期望C函数链接:- 正如您所注意到的,C函数有一个不同的名称mangling(即none)
为了解决您的问题,在您的头中声明一个干净的C风格API,如果您打算在C++中实现函数并使用g++作为编译器/链接器,则必须在标题文件中的函数声明之前添加一个<代码>外部“C”<代码>声明,或者作为声明的一个块:
extern "C" void print_array(...);
这将阻止C++名称的修改。
使用接口函数中的向量和其他C++类型会导致ABI问题。E“它不会工作”,即使所有的链接和编译看起来都很干净
使用C++函数,将函数中的cType(参见)支持的数据类型作为接口,在C++中实现,但在“代码”>“外部”“C”<代码>块中,将C函数声明包起来,以防止名称的篡改。
请参考cType的文档,以了解如何正确使用结构、联合、引用等作为函数参数,因为有许多陷阱和问题需要考虑。
注意它是如何说的,<代码>未定义的符号:PrrtPyLabeS/<代码>。它看起来像是符号。所以是< >代码> 11PrrtPrtayRaykt6VVTrISISIfIFSAESEAIS1EE EE /Cube >您已经被C++ ABI击中。请注意它是怎么说的,未定义符号:print\u array
。它看起来像是符号。所以是< >代码> 11PrrtPrtayRaykt6VVTrISISIfIFSAESEAIS1EE EE /Cube >您已经被C++ ABI击中。请看,我同意,我将坚持使用数组,因为我不需要动态结构。@mdoubez你在说什么?将C++函数标记为<代码>外部“C”<代码>绝对是好的。code>extern“C”告诉编译器不要对函数执行名称修改,而是发出一个与C兼容的符号。它还修改调用约定,“C”没有参数std::vector&的调用约定。不能将相同的函数暴露给C编译器。将NUMPY数组传递为浮点*VAR。然后,在内部函数中转换为C++类型。这个方法对我很有效!同意,我将坚持使用数组,因为我不需要动态结构。@mdoubez你在说什么?将C++函数标记为<代码>外部“C”<代码>绝对是好的。code>extern“C”告诉编译器不要对函数执行名称修改,而是发出一个与C兼容的符号。它还修改调用约定,“C”没有参数std::vector&的调用约定。不能将相同的函数暴露给C编译器。将NUMPY数组传递为浮点*VAR。然后,在内部函数中转换为C++类型。这个方法对我很有效!
extern "C" void print_array(...);