0
votes

My goal is to use ctypes to call from within Python a C++ library I'm creating separately, where I am passing numpy vectors to the C++ routines via pointers. So Python would allocate the memory and just pass the address, and then the C++ routine would access the data and perform its calculations and return the results.

Since I'm new to ctypes, right now I'm gradually building a working toy example. I'm starting off writing the C++ code and creating a C extern interface that the Python wrapper code will use. I haven't even started on the Python wrapper code yet but have some experience with that aspect already.

Here is my example which includes a constructor and a simple total function.

// 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();}
}

Note in particular that I'm using the vector class from the STL, which may be part of the problem described below. The idea is that the class Data holds a pointer to the data and does not replicate the data.

When I try to compile this using the command

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

on our Linux machine, I get the following error:

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&)

This seems pretty clear to me: it's saying that the way I call the Data constructor in the third to last line (#26) in foo.cpp does not coincide with the constructor I wrote in the C++ part of the code. In both the C++ code and the C extern code, I'm trying to say that the input is a pointer to a vector/array of doubles. I've tried other options on line #36 but it still doesn't compile.

How do I write the extern C part while still using the vector class (which I will find useful when I code the real algorithm) in the C++ part? Am I running into trouble because vector is part of the STL, which doesn't work well with extern C?

Thanks in advance.

1
If you want the Date_new and Print_total functions to be usable from a C program, then that won't work. Even when using extern "C" the C program will not be able to use classes like Data. - Some programmer dude

1 Answers

0
votes

First, let's answer your question. You should change your constructor so that it takes the same arguments as Data_new, and converts the input into a std::vector. However, it looks like there are a couple of conceptual issues that you need to focus on first:

  • Arrays and vectors are not equivalent: if your input points to an array, but you want to work with a vector, you'll need to copy all of the elements from the array into the vector (or ask a vector constructor to do it for you). You need to do the copy because all STL containers hold onto copies of the elements that are put in them.

  • You can construct the vector using two iterators, with:

    myContents(data, data + numberOfElements);

    But this brings up the second conceptual point --- there is nothing in the signature of your code that tells you how large the input array is.

  • In Data you're holding onto a pointer to a vector, but you never free it. This is a memory leak. That being said, you should probably just hold onto a vector, not a pointer to a vector.