关于访问C初始化ctypes结构元素的Segfault

时间:2011-08-18 14:39:32

标签: python c ctypes ffi

我正在尝试从ctypes访问结构的元素。该结构在C代码的init函数中创建,指向它的指针返回给Python。我遇到的问题是我在尝试访问返回结构的元素时遇到了段错误。这是代码:

C代码(我称之为ctypes_struct_test.c):

#include <stdio.h>
#include <stdbool.h>

typedef struct {
    bool flag;
} simple_structure;

simple_structure * init()
{
    static simple_structure test_struct = {.flag = true};
    if (test_struct.flag) {
        printf("flag is set in C\n");
    }
    return &test_struct;
}

Python代码(我称之为ctypes_struct_test.py):

#!/usr/bin/env python

import ctypes
import os

class SimpleStructure(ctypes.Structure):
    _fields_ = [('flag', ctypes.c_bool)]

class CtypesWrapperClass(object):

    def __init__(self):

        cwd = os.path.dirname(os.path.abspath(__file__))
        library_file = os.path.join(cwd,'libctypes_struct_test.so')

        self._c_ctypes_test = ctypes.CDLL(library_file)

        self._c_ctypes_test.init.restypes = ctypes.POINTER(SimpleStructure)
        self._c_ctypes_test.init.argtypes = []

        self.simple_structure = ctypes.cast(\
                self._c_ctypes_test.init(),\
                ctypes.POINTER(SimpleStructure))


a = CtypesWrapperClass()
print 'Python initialised fine'
print a.simple_structure.contents
print a.simple_structure.contents.flag

C在Linux下编译如下:

gcc -o ctypes_struct_test.os -c --std=c99 -fPIC ctypes_struct_test.c
gcc -o libctypes_struct_test.so -shared ctypes_struct_test.os

在运行python ctypes_struct_test.py时,我得到以下输出:

flag is set in C
Python initialised fine
<__main__.SimpleStructure object at 0x166c680>
Segmentation fault

我正在尝试做什么,或者我尝试做的方式有问题吗?

2 个答案:

答案 0 :(得分:4)

要使其工作,请更换错误的行

self._c_ctypes_test.init.restypes = ctypes.POINTER(SimpleStructure)

通过正确的行

self._c_ctypes_test.init.restype = ctypes.POINTER(SimpleStructure)

还要考虑删除无意义的演员

self.simple_structure = ctypes.cast(
    self._c_ctypes_test.init(), ctypes.POINTER(SimpleStructure))

它从ctypes.POINTER(SimpleStructure)投射到ctypes.POINTER(SimpleStructure)

答案 1 :(得分:1)

你在你的init例程中将test_struct声明为一个静态局部变量 - 我乍一看我很怀疑。 (忍受我;我的C有点生锈。)

C中的静态局部变量应该在对同一函数的多次调用中保持不变,但它们的范围与自动局部变量相同 - 并返回指向自动局部变量的指针肯定会给你一个段错误。即使你通常在C语言中从同一个翻译单元调用该函数,这通常也会起作用,你从Python调用它的事实(以及你试图访问结构时就是segffeulting)是红色的标志。

尝试在init例程中使用malloc()并返回从中获取的指针,而不是返回指向静态变量的指针。

[[[警告:这会导致内存泄漏。 ]]]

但那没关系;如果segfault消失了,你会知道这就是问题所在。然后,您可以通过在C代码中提供调用free()的第二个例程来确定内存泄漏,并确保在完成结构时从python代码中调用它。

相关问题