ctypes: pointer to method

M

Martin Landa

Hi,

is it possible to pass pointer to a method using ctypes. Sample code:

...
G_set_error_routine(byref(self._print_error))
...

def _print_error(self, msg, type):
"""!Redirect stderr"""
self.log.write(msg)

gives me

G_set_error_routine(byref(self._print_error))
TypeError: byref() argument must be a ctypes instance, not
'instancemethod'


C function G_set_error_routine is defined as

void G_set_error_routine(int (*error_routine) (const char *, int))

Thanks in advance for any pointers. Martin
 
N

Nobody

is it possible to pass pointer to a method using ctypes.

I don't know about methods, but it works for functions.
Sample code:

...
G_set_error_routine(byref(self._print_error))

This won't work; you have to be more explicit, e.g.:

errtype = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_int))
errfunc = errtype(print_error)
G_set_error_routine(errfunc)

NOTE: be sure to keep a reference to the wrapper, as ctypes doesn't hold
references itself. IOW, you can't replace the above with:

errtype = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_int))
G_set_error_routine(errtype(print_error))

If you do this, the wrapper is eligible for garbage collection as soon as
G_set_error_routine() returns, and will probably have vanished by the time
that G_fatal_error() gets called.

For more information see:

http://docs.python.org/library/ctypes.html#callback-functions
 
M

Martin Landa

Hi,

I don't know about methods, but it works for functions.



This won't work; you have to be more explicit, e.g.:

        errtype = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_int))
        errfunc = errtype(print_error)
        G_set_error_routine(errfunc)

the C function is defined as

G_set_error_routine = _libs['grass_gis.
7.0.svn'].G_set_error_routine
G_set_error_routine.restype = None
G_set_error_routine.argtypes = [CFUNCTYPE(UNCHECKED(c_int),
String, c_int)]

I defined in Python function print_error()

def print_error(self, msg, type):
print msg, type

and

errtype = CFUNCTYPE(UNCHECKED(c_int), String, c_int)
errfunc = errtype(print_error)
G_set_error_routine(errfunc)

unfortunately the application crashes when print_error() is called
from C library

static void vfprint_error(int type, const char *template, va_list ap)
{
char buffer[2000]; /* G_asprintf does not work */

vsprintf(buffer, template, ap);

G_debug(5, "print_error(): msg = \"%s\" type = %d", buffer, type);
print_error(buffer, type);
}

Any idea how to solve it. Thanks, Martin
 
M

Martin Landa

Hi,

Any idea how to solve it. Thanks, Martin

I overlooked note

"""
Make sure you keep references to CFUNCTYPE objects as long as they are
used from C code. ctypes doesn’t, and if you don’t, they may be
garbage collected, crashing your program when a callback is made.
"""

If I defined errtype and errfunc as global variable everything works.
Thanks again for your help. Martin
 
M

Martin Landa

Hi,

        errtype = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_int))
        errfunc = errtype(print_error)
        G_set_error_routine(errfunc)

the problem occurs when restype is not None, but c_int. E.g.

if hasattr(_libs['grass_gis'], 'G_set_error_routine'):
G_set_error_routine = _libs['grass_gis'].G_set_error_routine
G_set_error_routine.restype = c_int
G_set_error_routine.argtypes = [CFUNCTYPE(UNCHECKED(c_int),
String, c_int)]

errtype = CFUNCTYPE(UNCHECKED(c_int), String, c_int)
errfunc = errtype(print_error)

or

errtype = CFUNCTYPE(c_int, String, c_int)
errfunc = errtype(print_error)

ends up with error

G_set_error_routine(errfunc)
TypeError: in method 'G_set_error_routine', argument 1 of type 'int (*)
(char const *,int)'

The first argument of CFUNCTYPE defines result type (restype), AFAIU
that should work.

Thanks in advance again, Martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top