Python ctypes和librsvg出错

| 我正在尝试使用ctypes来包装librsvg的基本功能,但是我遇到了段错误。 C:
// pycairo excerpt
typedef struct {
  PyObject_HEAD
  cairo_t *ctx;
  PyObject *base; /* base object used to create context, or NULL */
} PycairoContext;

// librsvg excerpt
RsvgHandle * rsvg_handle_new_from_file (const gchar * file_name, GError ** error);
// ...
gboolean rsvg_handle_render_cairo (RsvgHandle * handle, cairo_t * cr);
Python ctypes:
from ctypes import *
from ctypes import util


librsvg = cdll.LoadLibrary(\'/brew/lib/librsvg-2.2.dylib\')
libgobject = cdll.LoadLibrary(\'/brew/lib/libgobject-2.0.dylib\')

libgobject.g_type_init()


class RSVGDimensionData(Structure):

    _fields_ = (
        (\'width\', c_int),
        (\'height\', c_int),
        (\'em\', c_double),
        (\'ex\', c_double)
    )

class PycairoContext(Structure):

    _fields_ = (
        (\'PyObject_HEAD\', c_byte * object.__basicsize__),
        (\'ctx\', c_void_p),
        (\'base\', c_void_p)
    )


class RSVGHandle(object):

    def __init__(self, path):
        self.path = path
        self.error = \'\'
        self.handle = librsvg.rsvg_handle_new_from_file(self.path, self.error)

    def render_cairo(self, context):
        context.save()
        z = PycairoContext.from_address(id(context))
        librsvg.rsvg_handle_render_cairo(self.handle, z.ctx)
        context.restore()


import cairo

h = RSVGHandle(\'bank.svg\')
s = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
ctx = cairo.Context(s)


# segmentation fault....
h.render_cairo(ctx)
该行发生错误::2ѭ 关于这有什么问题的任何想法吗?     
已邀请:
问题是未定义返回类型的规范。仅在结果上使用ѭ3不足以解决那种情况下的问题。你需要放
librsvg.rsvg_handle_new_from_file.restype = c_void_p
在适当的地方。然后,它(也)可以在OSX中以32位或64位工作。 但是,我发现增强基本包装更为有用,以便处理从文件创建句柄时可能出现的错误。以下是执行此操作的基本包装。它还以几乎相同的方式复制了标准“ 5”绑定的基本用法。
from ctypes import CDLL, POINTER, Structure, byref, util
from ctypes import c_bool, c_byte, c_void_p, c_int, c_double, c_uint32, c_char_p

class _PycairoContext(Structure):
    _fields_ = [(\"PyObject_HEAD\", c_byte * object.__basicsize__),
                (\"ctx\", c_void_p),
                (\"base\", c_void_p)]

class _RsvgProps(Structure):
    _fields_ = [(\"width\", c_int), (\"height\", c_int),
                (\"em\", c_double), (\"ex\", c_double)]

class _GError(Structure):
    _fields_ = [(\"domain\", c_uint32), (\"code\", c_int), (\"message\", c_char_p)]


def _load_rsvg(rsvg_lib_path=None, gobject_lib_path=None):
    if rsvg_lib_path is None:
        rsvg_lib_path = util.find_library(\'rsvg-2\')
    if gobject_lib_path is None:
        gobject_lib_path = util.find_library(\'gobject-2.0\')
    l = CDLL(rsvg_lib_path)
    g = CDLL(gobject_lib_path)
    g.g_type_init()

    l.rsvg_handle_new_from_file.argtypes = [c_char_p, POINTER(POINTER(_GError))]
    l.rsvg_handle_new_from_file.restype = c_void_p
    l.rsvg_handle_render_cairo.argtypes = [c_void_p, c_void_p]
    l.rsvg_handle_render_cairo.restype = c_bool
    l.rsvg_handle_get_dimensions.argtypes = [c_void_p, POINTER(_RsvgProps)]

    return l    

_librsvg = _load_rsvg()


class Handle(object):
    def __init__(self, path):
        lib = _librsvg
        err = POINTER(_GError)()
        self.handle = lib.rsvg_handle_new_from_file(path.encode(), byref(err))
        if self.handle is None:
            gerr = err.contents
            raise Exception(gerr.message)
        self.props = _RsvgProps()
        lib.rsvg_handle_get_dimensions(self.handle, byref(self.props))

    def render_cairo(self, ctx):
        \"\"\"Returns True is drawing succeeded.\"\"\"
        z = _PycairoContext.from_address(id(ctx))
        return _librsvg.rsvg_handle_render_cairo(self.handle, z.ctx)
用法示例可以在https://stackoverflow.com/a/14928770/1832154上看到。     
librsvg.rsvg_handle_render_cairo需要指针,而是获取整数。这里不确定整个故事,但是这种修改至少不会引起段错误。 尝试这个
 librsvg.rsvg_handle_render_cairo(c_void_p(self.handle), c_void_p(z.ctx))
注意,我将两个参数包装在c_void_p中,使它们成为void *指针。不理想,但似乎可行。     

要回复问题请先登录注册