РЕДАКТИРОВАТЬ: Этот вопрос решен. При разработке небольшого примера ниже все работает как положено. Я оставил это на случай, если кто-нибудь найдет это полезным. Очевидно, что моя проблема проистекает из другого места.
Я использую Cython для написания интерфейса Python для программы на C ++. Программа C ++ использует непрерывный массив структур в качестве входных данных. Я могу создать массив или вектор этих структур в Cython и передать его программе C ++. Хотя предполагается, что эти контейнеры являются смежными, когда C ++ выполняет итерации по ним (посредством увеличения указателя на первый элемент), становится ясно, что они не являются смежными. Распечатка одного из полей структур показывает много мусора.
В качестве примера интерфейса Python:
cdef extern from "program.h" namespace "Thing":
struct Thing:
int id
int datacdef 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
Тогда вот пример кода C ++. Первый «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);
};
};
Теперь «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;
}
Теперь предположим, что я запускаю следующий код Python
MyObject = PyProgram(0, 0)
MyObject.Main([(1, 2), (3, 4), (5, 6)])
Это печатает 1,3, 5, как и ожидалось. Так что я не знаю, почему этот упрощенный пример работает, но моя настоящая программа выплевывает мусор. Думаю, я оставлю этот пример здесь на тот случай, если кто-нибудь еще посчитает его полезным, но на данный момент глупо отвечать на мой собственный вопрос.
Чтобы более точно отразить мой код, вот что не сделать.
Предположим, что мы определяем Программу следующим образом:
class Program{
public:
int attr1;
int attr2;
Thing* thing;
Program(int attr1, int attr2, Thing* thing): attr1(attr1), attr2(attr2),
thing(thing){};
void Main(int size);
};
Затем в «program.cpp»
void Program::Main(int size){
for (int i=0; i<size; ++i){
cout << (Things+i)->id << endl;
}
}
После внесения соответствующих изменений в интерфейс, проблема начнет возникать. Правильный способ сделать это в примере с игрушкой выше. Я сделал это изменение, и все заработало.
Я назвал это ответом, который немного задом наперед, поскольку в этом посте содержится ошибка, а в оригинальном посте содержится ответ. Если сообщество сочтет это лучше, как комментарий, я изменю это.
Других решений пока нет …