Error with python and librsvg types

I am trying to wrap the main librsvg ctypes function for Python, but I get segfault.

FROM

// 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); 

Types of python:

 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 in this line is: librsvg.rsvg_handle_render_cairo(self.handle, z.ctx)

Any idea what is wrong with this?

+4
source share
2 answers

The problem is that the specification of the return type is not defined; using c_void_p just one result is not enough to solve the problem in this case. You need to put

 librsvg.rsvg_handle_new_from_file.restype = c_void_p 

in the appropriate place. Then it (also) runs on OSX in either 32 bits or 64 bits.

But I found it more useful to increase the basic packaging to handle possible errors when creating a handle from a file. Below is the base shell. It is also replicated in a largely identical way by the basic use of standard rsvg bindings.

 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, 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) 

A usage example can be seen at fooobar.com/questions/892722 / ....

+5
source

librsvg.rsvg_handle_render_cairo expects pointers and gets integers instead. Not sure about the full story here, but this modification is at least not a secret.

try it

  librsvg.rsvg_handle_render_cairo(c_void_p(self.handle), c_void_p(z.ctx)) 

Note that I wrapped two parameters in c_void_p to turn them into void * pointers. Not perfect, but it seems to work.

+3
source

Source: https://habr.com/ru/post/892714/


All Articles