-----Original Message-----
From: eryk sun [mailto:eryk...@gmail.com] 
Sent: 03 August 2016 13:16
To: python-list@python.org
Cc: Bill Somerville <bsomervi...@flexerasoftware.com>
Subject: Re: Issue with ctypes and callback functions

On Wed, Aug 3, 2016 at 9:38 AM, Bill Somerville 
<bsomervi...@flexerasoftware.com> wrote:
>
> Is this a good place to ask questions about the above?

Discussing ctypes is fine here. There's also a ctypes-users list.


Thanks Eryk,

I am trying to handle Python callback functions in a SWIG interface, SWIG does 
not support callbacks where the target is a Python callable but I can do this 
with ctypes. My problem is that I need to have the callback receive a SWIG 
wrapped type as an argument by reference. I see that if I use a 
ctypes.Structure type then it works nicely but I have a huge and changing API 
to wrap and do not want to manually describe every C struct with 
ctypes.Structure when SWIG has already automatically created its own shadow 
classes. The SWIG struct wrapper is just a class wrapping a pointer so can be 
easily be passed just like ctypes.Structure can be. How do I tell ctypes that 
it needs to reconstitute the type from an address in the callback thunk it 
generates?

I have tried defining from_param() and self._as_parameter_ for the types which 
works for passing to a function but I don't need that as SWIG does that 
already. With callback arguments I get various errors depending on what 
methods/attributes I supply like:

Parsing argument 0
TypeError: cannot build parameter

At the point where the callback is being called.

To summarize:
++++++++++++++++++++++++++++++++++++
C API like:

typedef struct {
    int member;
    /* ... */
} my_type;
typedef int (*pfn) (my_type const *);
int fn (pfn);

Implementation could be:

#include "api.h"
int fn (pfn cb) {
    my_type t = {42, /* ... */};
    return cb (&t);
}

I want Python code like:

from ctypes import *
import api  # SWIG extension module

def my_cb (t):
    print ('in callback with:', t.member)
    return 0

proto = CFUNCTYPE (c_int, my_type)
cb = proto (my_cb)
res = api.fn (cast (cb, c_void_p).value)
print ('fn returned:', res)

------------------------------------------------

I can extend the SWIG shadow class to do the creation of the prototype and 
thunk, the required cast above and any extra attributes or methods like 
_as_parameter_ and from_param() but I can't see any way of having the Python 
callback (my_cb) magically receive the SWIG wrapped 'my_type' struct.

TIA
Bill.
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to