Python ctypes 和 librsvg 错误
我正在尝试使用 Python 的 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)
错误发生在这一行:librsvg.rsvg_handle_render_cairo(self.handle, z.ctx)
知道这有什么问题吗?
I'm trying to wrap basic function of librsvg with ctypes for Python, but I'm getting a segfault.
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)
The error is happening in this line: librsvg.rsvg_handle_render_cairo(self.handle, z.ctx)
Any idea about what's wrong with this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是没有定义返回类型的规范;仅对结果使用
c_void_p
不足以解决这种情况下的问题。你需要放在合适的地方。然后它(也)可以在 OSX 中以 32 位或 64 位运行。
但我发现增强基本包装更有帮助,以便处理从文件创建句柄时可能出现的错误。以下是执行此操作的基本包装器。它还以几乎相同的方式复制了标准 rsvg 绑定的基本用法。
示例用法请参见 https://stackoverflow.com/a/14928770/1832154。
The problem is that the specification of the return type is not defined; using
c_void_p
on the result alone isn't enough to solve the problem in that case. You need to putin an appropriate place. Then it (also) works in OSX either in 32 bits or 64 bits.
But I've found more helpful to augment the basic wrapping in order to handle possible errors when creating a handle from a file. Following is a basic wrapper that does that. It also replicates in a mostly identical way the basic use of the standard
rsvg
bindings.Example usage can be seen at https://stackoverflow.com/a/14928770/1832154.
librsvg.rsvg_handle_render_cairo 需要指针,并且正在获取整数。不确定这里的整个故事,但这种修改至少不会出现段错误。
试试这个
注意,我将两个参数包装在 c_void_p 中,使它们成为 void * 指针。不理想,但似乎有效。
librsvg.rsvg_handle_render_cairo expects pointers, and is getting integers instead. Not sure of the entire story here but this modification at least does not segfault.
Try this
Notice I wrapped the two parameters in c_void_p to make them into void * pointers. Not ideal, but it seems to work.