Я не чужд модулю python ctypes, но это моя первая попытка комбинировать C++, C и Python все в одном коде. Моя проблема, похоже, очень похожа на Seg fault when using ctypes with Python and C++, однако, похоже, я не мог решить проблему точно так же.ctypes/C++ segfault доступ к переменным-членам
У меня есть простой файл 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, я должен получить numbe r 32 печатается на экране. Однако все, что я получаю, это ошибка сегментации. Если я изменю конструктор, чтобы вернуть экземпляр класса в стек (т. Е. Без вызова new
), а затем обойти объект, программа выполняет как ожидалось. Кроме того, если я изменю метод bar
в классе Foo
, так что он не использует член nbits
, программа не выполняет никаких сбоев.
У меня ограниченное понимание C++, но тот факт, что я могу сделать эту функцию ожидаемой в C и на C++, но не в Python, немного запутан. Любая помощь будет принята с благодарностью.
Обновление: Благодаря одному из приведенных ниже комментариев проблема решена. В этом случае требовалось явное объявление как restype, так и argtypes для C-функций. то есть следующий был добавлен к коду:
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];
Работы для меня. Также возможно Исправление: Я предполагаю, что вы скомпилировали Header.cpp с помощью переключателя -fPIC? – udoprog
Работает здесь тоже. Просьба указать gdb backtrace segfault. –
Работает для меня тоже. Вы перемещаете указатель на Foo как C int, который может завершиться неудачей. Попробуйте указать функции argtypes и restype, например. '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]' – cgohlke