Создание непрерывного массива в Cython и передача его в переполнение стека

РЕДАКТИРОВАТЬ: Этот вопрос решен. При разработке небольшого примера ниже все работает как положено. Я оставил это на случай, если кто-нибудь найдет это полезным. Очевидно, что моя проблема проистекает из другого места.

Я использую 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, как и ожидалось. Так что я не знаю, почему этот упрощенный пример работает, но моя настоящая программа выплевывает мусор. Думаю, я оставлю этот пример здесь на тот случай, если кто-нибудь еще посчитает его полезным, но на данный момент глупо отвечать на мой собственный вопрос.

0

Решение

Чтобы более точно отразить мой код, вот что не сделать.

Предположим, что мы определяем Программу следующим образом:

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;
}
}

После внесения соответствующих изменений в интерфейс, проблема начнет возникать. Правильный способ сделать это в примере с игрушкой выше. Я сделал это изменение, и все заработало.

Я назвал это ответом, который немного задом наперед, поскольку в этом посте содержится ошибка, а в оригинальном посте содержится ответ. Если сообщество сочтет это лучше, как комментарий, я изменю это.

0

Другие решения

Других решений пока нет …