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?
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.
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.