将 C++ 中的“extern C”与 ctypes 的向量一起使用

Posted

技术标签:

【中文标题】将 C++ 中的“extern C”与 ctypes 的向量一起使用【英文标题】:Using "extern C" from C++ with vector for ctypes 【发布时间】:2012-08-28 23:47:55 【问题描述】:

我的目标是使用 ctypes 从 Python 中调用我正在单独创建的 C++ 库,其中我通过指针将 numpy 向量传递给 C++ 例程。因此 Python 将分配内存并传递地址,然后 C++ 例程将访问数据并执行其计算并返回结果。

由于我是 ctypes 的新手,现在我正在逐步构建一个工作玩具示例。我开始编写 C++ 代码并创建 Python 包装器代码将使用的 C 外部接口。我什至还没有开始编写 Python 包装器代码,但已经在这方面有了一些经验。

这是我的示例,其中包括一个构造函数和一个简单的总函数。

// foo.cpp //
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Data 
public:
  Data(vector<double>*);
  void PrintTotal(void);
private:
  vector<double>* myContents;
;
Data::Data(vector<double>* input) 
  std::cout << "Entered constructor in C++" << std::endl;
  myContents = input;

void Data::PrintTotal(void) 
  double total = 0;
  for (int i=0; i<myContents->size(); i++)
    total += (*myContents)[i];
  
  std::cout << "Hello, my total is " << total << std::endl;


extern "C" 
  Data* Data_new(double (**input)) return new Data(input);
  void Print_Total(Data* pData) pData->PrintTotal();

请特别注意,我使用的是 STL 中的矢量类,这可能是下面描述的问题的一部分。这个想法是 Data 类持有指向数据的指针,并且不会复制数据。

当我尝试使用命令编译时

g++ -c -fPIC foo.cpp -o foo.o

在我们的 Linux 机器上,我收到以下错误:

foo.cpp: In function âData* Data_new(double**)â:
foo.cpp:26: error: no matching function for call to âData::Data(double**&)â
foo.cpp:13: note: candidates are: Data::Data(std::vector<double, std::allocator<double> >*)
foo.cpp:6: note:                 Data::Data(const Data&)

这对我来说似乎很清楚:它是说我在 foo.cpp 的倒数第三行 (#26) 中调用 Data 构造函数的方式与我在代码的 C++ 部分中编写的构造函数不一致。在 C++ 代码和 C extern 代码中,我想说输入是指向双精度向量/数组的指针。我在第 36 行尝试了其他选项,但仍然无法编译。

如何在 C++ 部分中仍然使用 vector 类(在编写真正的算法时会发现它很有用)的同时编写 extern C 部分?我是不是因为vector 是STL 的一部分而遇到麻烦,它不能很好地与extern C 配合使用?

提前致谢。

【问题讨论】:

如果您希望 Date_newPrint_total 函数可以在 C 程序中使用,那么这是行不通的。即使使用extern "C",C 程序也无法使用像Data 这样的类。 【参考方案1】:

首先,让我们回答您的问题。您应该更改您的构造函数,使其采用与 Data_new 相同的参数,并将输入转换为 std::vector。但是,您首先需要关注几个概念性问题:

数组和向量不等价:如果您的输入指向 数组,但你想使用向量,你需要复制 将数组中的所有元素放入向量中(或询问 向量构造函数为你做这件事)。你需要做副本 因为所有 STL 容器都保存了元素的副本 放进去。

您可以使用两个迭代器构造向量,其中:

myContents(data, data + numberOfElements);

但这引出了第二个概念点 --- 代码签名中没有任何内容可以告诉您输入数组有多大。

在 Data 中,您持有指向向量的指针,但您 永远不要释放它。这是内存泄漏。话虽如此,你应该 可能只是持有一个向量,而不是一个指向向量的指针。

【讨论】:

以上是关于将 C++ 中的“extern C”与 ctypes 的向量一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 ctypes 将 (uint8) NumPy 数组从 python 传递到 c++

使用 ctypes 在 Python 中解码 C const char*

通过 ctypes 使用扩展 dll 中的类需要帮助

extern “C”

C++ Primer 5th笔记(chap 19 特殊工具与技术)链接指示: extern “C“

C DLL 和 Python CTypes - 发布/调试中的不同返回