我对ctypes很新,我在下面的简单程序中遇到错误。
Foo.cpp中
class Foo {
public:
int bar;
Foo(int bar): bar(bar) {}
};
extern "C" {
Foo * Foo_new(int bar) {
return new Foo(bar);
}
int Foo_bar(Foo *foo) {
return foo->bar;
}
}
foo.py
import ctypes
libfoo = ctypes.CDLL('libfoo.so')
class Foo:
def __init__(self, bar):
self.foo = libfoo.Foo_new(bar)
def bar(self):
return libfoo.Foo_bar(self.foo)
foo = Foo(5)
print(foo.bar())
当我调用libfoo.Foo_bar(self.foo)
时会发生细分错误,但根据this answer,我认为我需要做的就是通过self.foo
做一个强引用,这样它就不是垃圾了集。
我的猜测是Foo
是在CPP文件的堆栈上进行的,因此在进行函数调用后会立即擦除它。在任何情况下,我该如何解决这个问题?
答案 0 :(得分:3)
您必须显式地包装参数和返回类型,否则ctypes
将假设某些可能或可能不起作用的任意默认值。要将指针包装到类Foo
,我使用指向void c_void_p
的指针。我不确定这是否是正确的方法,但似乎有效。
import ctypes
libfoo = ctypes.CDLL('libfoo.so')
libfoo.Foo_new.argtypes = [ctypes.c_int]
libfoo.Foo_new.restype = ctypes.c_void_p
libfoo.Foo_bar.argtypes = [ctypes.c_void_p]
libfoo.Foo_bar.restype = ctypes.c_int
class Foo:
def __init__(self, bar):
self.foo = libfoo.Foo_new(bar)
def bar(self):
return libfoo.Foo_bar(self.foo)
foo = Foo(5)
print(foo.bar())
我通常采用不同的途径通过使用SWIG生成Python扩展来将C ++代码与Python接口。因此,我会写一个文件test.h
class Foo {
public:
int bar;
Foo(int bar): bar(bar) {}
};
然后我会写一个SWIG接口文件test.i
%module test
%{
#include "test.h"
%}
%include "test.h"
然后我在终端
执行$ swig -python -c++ test.i
$ c++ -fpic -shared -I/usr/include/python2.7 test_wrap.cxx -o _test.so
然后我可以用Python脚本编写
from test import Foo
foo = Foo(5)
print foo.bar