EDIT: This question is resolved. In working out the small example below, everything works as expected. I have left it in case anyone finds it helpful. Obviously, my problem is stemming from elsewhere.
I am using Cython to write a Python interface for a C++ program. The C++ program uses a contiguous array of structs as input. I can create an array or vector of these structs in Cython and pass it to the C++ program. While these containers are supposed to be contiguous, when C++ iterates over them (via incrementing the pointer to the first element), it becomes clear that they are not contiguous. Printing out one of the fields of the structs reveals lots of garbage output.
As an example of the Python interface:
cdef extern from "program.h" namespace "Thing":
struct Thing:
int id
int data
cdef extern from "program.h" namespace "Thing":
cdef cppclass Program:
int attribute_1
int attribute_2
void Program(int attr1, int attr2) except +
void Main(Thing* Things)
cdef class PyProgram:
cdef Program* c_Program
def __cinit__(self, int attr1, int attr2):
self.c_Program = new Program (attr1, attr2)
cpdef void Main(self, list things):
cdef vector[Thing] Things # This should be contiguous!
for t in things:
Things.push_back(self.make_a_thing(t[0], t[1]))
self.c_Program.Main(&Things[0], len(Things))
cdef make_a_thing(self, int id, int data):
cdef Thing c = Thing(id, data)
return c
Then here is some example C++ code. First "program.h"
#include <vector>
#include <iostream>
namespace Thing{
struct Thing{
int id;
int data;
};
class Program{
public:
int attr1;
int attr2;
Program(int attr1, int attr2): attr1(attr1), attr2(attr2){};
void Main(Thing* Thing, int size);
};
};
Now "program.cpp"
#include "program.h"
#include <iostream>
using namespace Thing;
using namespace std;
void Program::Main(Thing* Things, int size){
for (int i=0; i<size; ++i){
cout << (Things+i)->id << endl;
}
}
int main(){
return 0;
}
Now suppose I run the following Python code
MyObject = PyProgram(0, 0)
MyObject.Main([(1, 2), (3, 4), (5, 6)])
This prints 1,3, 5 as expected. So I don't know why this simplified example works but my real program spits out garbage. I guess I'll leave this example here in case anyone else finds it useful, but it seems silly to answer my own question at this point.