0

我有交流功能:

extern "C"  __declspec(dllexport) MyStruct foo()
{
    MyStruct s = {0, 0}
    return s;
}

其中 MyStruct 定义为:

struct MyStruct{
    uInt32   a;
    uInt32   b;
    void *   c;
};

我试图在 python 中调用该函数,但总是得到如下错误:

WindowsError:异常:访问冲突写入 0x00000000

如果我从结构中删除 void * c,那么它可以工作......

那么我应该如何返回 void 指针?谢谢!

4

4 回答 4

3

这几乎可以肯定是由于您的 C 编译器和 ABI 上的 ctypes 库在返回对象方面存在分歧。如果没有看到您的 Python 代码,很难说问题是由于返回类型的错误 Python 声明、ctypes 库中的错误还是 C 编译器选择的非标准 ABI 造成的。

对于最便携的行为,我建议更改函数以通过 out 参数返回对象,如下所示:

extern "C"  __declspec(dllexport) void foo(MyStruct *ret)
{
    MyStruct s = {0, 0}
    *ret = s;
}

并像这样与它交互:

class MyStruct(ctypes.Structure):
    _fields_ = [("a", ctypes.c_uint),
                ("b", ctypes.c_uint),
                ("c", ctypes.c_void_p)]

mylib = ctypes.cdll.LoadLibrary('mylibrary')
foo = mylib.foo
foo.argtypes = [ctypes.POINTER(MyStruct)]

x = MyStruct()
foo(ctypes.byref(x))
# x should now have the return value from the C code
于 2012-07-23T22:13:50.160 回答
1

我看不出你是在分配你的void* c. 我在任何地方都没有看到它,但它似乎稍后在某处被读取(即access violation writing 0x00000000,一个 NULL 指针)。因此,c需要在取消引用之前对其进行初始化。

似乎 的值c恰好在0这里,但并非必须如此。它没有静态存储持续时间,并且您没有对其进行初始化(您仅使用ab进行了初始化{0, 0}),因此c可以具有任何值。碰巧的是,在我的测试用例中,它c驻留在已初始化的内存区域中0(即使在发布时)。这不能保证。

我敢打赌你正在做类似的事情:

MyStruct s = foo();
*((some_type*)s.c) = some_value;  // BLAMOOO! c is uninitialized

你还没有发布使用返回值的代码,所以这是我能给你的最好猜测。

于 2012-07-23T22:10:44.947 回答
0

如果您展示您的 Python 代码,将会有所帮助。您需要定义结构和返回类型foo

from ctypes import *

class MyStruct(Structure):
    _fields_ = [
        ('a',c_int),
        ('b',c_int),
        ('c',c_void_p)]

mydll = CDLL('mydll')
mydll.foo.restype = MyStruct

r = mydll.foo()
print r.a
print r.b
print r.c
于 2012-07-24T01:52:36.747 回答
-2

在堆上分配您的结构并返回指向它的指针,而不是在堆栈上分配它。当您在堆栈上分配事物时,它们是短暂的,即它们在从子例程返回时由机器自动释放。

查找mallocman malloc)/见这里: http: //linux.die.net/man/3/malloc

于 2012-07-23T22:01:38.760 回答