python — ctypes / C ++ segfault для доступа к переменным-членам

Я не новичок в модуле Python ctypes, но это моя первая попытка объединить C ++, C и Python в одном коде. Кажется, моя проблема очень похожа на Ошибка сегмента при использовании ctypes с Python и C ++, однако я не мог решить проблему таким же образом.

У меня есть простой файл C ++ под названием Header.cpp:

#include <iostream>

class Foo{
public:
int nbits;
Foo(int nb){nbits = nb;}
void bar(){ std::cout << nbits << std::endl; }
};

extern "C" {
Foo *Foo_new(int nbits){ return new Foo(nbits); }
void Foo_bar(Foo *foo){ foo->bar(); }
}

который я компилирую в общую библиотеку, используя:

g++ -c Header.cpp -fPIC -o Header.o
g++ -shared -fPIC -o libHeader.so  Header.o

и простая оболочка Python под названием test.py:

import ctypes as C
lib = C.CDLL('./libHeader.so')

class Foo(object):
def __init__(self,nbits):
self.nbits = C.c_int(nbits)
self.obj = lib.Foo_new(self.nbits)

def bar(self):
lib.Foo_bar(self.obj)

def main():
f = Foo(32)
f.bar()

if __name__ == "__main__":
main()

Я ожидаю, что когда я вызову test.py, я выведу число 32 на экран. Однако все, что я получаю, это ошибка сегментации. Если я изменю конструктор, чтобы он возвращал экземпляр класса в стеке (т.е. без new вызов), а затем обойти объект, программа выполняет, как ожидалось. Кроме того, если я изменю bar метод в Foo класс такой, что он не использует nbits участник, программа не вызывает ошибки.

У меня ограниченное понимание C ++, но тот факт, что я могу сделать эту функцию, как ожидается, в C и в C ++, но не в Python, немного сбивает с толку. Любая помощь будет принята с благодарностью.

Обновить: Благодаря одному из комментариев ниже, проблема была решена. В этом случае для функций C требовалось явное объявление как restype, так и argtypes. Т.е. к коду добавлено следующее:

lib.Foo_new.restype  = C.c_void_p;
lib.Foo_new.argtypes = [C.c_int32];
lib.Foo_bar.restype  = None;
lib.Foo_bar.argtypes = [C.c_void_p];

2

Решение

Я бы попробовал следующее:

extern "C"{
Foo *Foo_new(int nbits)
{
Foo *foo = new Foo(nbits);
printf("Foo_new(%d) => foo=%p\n", nbits, foo);
return foo;
}
void Foo_bar(Foo *foo)
{
printf("Foo_bar => foo=%p\n", foo);
foo->bar();
}
}

чтобы увидеть, если значения foo матч.

Кроме того, вы можете захотеть взглянуть на Boost.Python, чтобы упростить создание привязок Python для объектов C ++.

0

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

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

По вопросам рекламы [email protected]