我正在尝试从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";
}
}
}
和头文件
#ifndef ADD_H
#define ADD_H
#include <vector>
void print_array(const std::vector<std::vector<float>> &A);
#endif
我试图建造
g++ -fpic -c print.cpp -o print.o
g++ -shared -o print.so print.o
然后用python
from cytpes import cdll
print_lib = cdll.LoadLibrary("print.so")
线
print_lib.print_array()
收益
AttributeError: ./print.so: undefined symbol: print_array
nm -D print.so
提供输出
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
在编译步骤中,我从根本上做错了什么?
答案 0 :(得分:4)
您正在调用C ++函数,而ctypes
需要C函数链接:
要解决您的问题,请在标头中声明一个干净的C样式API,如果您打算在C ++中实现这些功能并使用g ++作为编译器/链接器,则必须在此之前添加一个extern "C"
声明头文件中的函数声明,或作为声明周围的块:
extern "C" void print_array(...);
这将防止C ++名称混乱。
在接口函数中使用向量和其他C ++类型将引起ABI问题,即。 e。即使所有内容看上去都可以干净地链接和编译,“它也不会起作用”。
在函数中将C函数与ctypes支持的数据类型一起使用(请参阅Python docs on ctypes)作为接口,可以在C ++中随意实现,然后将C函数声明包装在extern "C"
块中以防止名称篡改。
请务必参考ctypes的文档,以了解如何正确地 使用结构,联合,引用等作为函数参数,因为有很多陷阱和问题需要考虑。