从单个.cpp构建共享对象

时间:2018-06-27 19:49:56

标签: 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; 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

在编译步骤中,我从根本上做错了什么?

1 个答案:

答案 0 :(得分:4)

您正在调用C ++函数,而ctypes需要C函数链接:

    如您所见,
  • C函数具有不同的名称处理(即,没有)
  • C函数不能具有C ++参数(std对象,例如std :: vector,引用等)

要解决您的问题,请在标头中声明一个干净的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的文档,以了解如何正确地 使用结构,联合,引用等作为函数参数,因为有很多陷阱和问题需要考虑。

相关问题