On 31-10-2019 15:39, Arnaud Loonstra wrote:
On 31-10-2019 14:44, Thomas Jollans wrote:
On 31/10/2019 14.13, Arnaud Loonstra wrote:
On 30-10-2019 09:32, Arnaud Loonstra wrote:
Hi all,
I'm trying to wrap my head around the ctypes API. I have a C
structure I wish to create in Python and then return from python to C.
So a python method is called from C and needs to return an object
which we then process in C again.
I have a binding to access and create the C methods and structures so
in Python I can call the Zmsg() constructor. I now need to return this.
My python test method is simply:
def actor_test( *args, **kwargs):
print("test")
msg = Zmsg()
frame = Zframe(b"Hello", 5)
msg.prepend(frame)
return msg
the method is called from C as follows:
PyObject *pReturn = PyObject_CallObject(pFunc, NULL);
This correctly calls the method. However the returned object is of
course a PyObject*. The debugger says it's
"<czmq._czmq_ctypes.Zmsg object at 0x7ffff5f18e50>" PyObject
[class] "<class 'czmq._czmq_ctypes.Zmsg'>"
[super class] "<class 'object'>"
[meta type] "<class 'type'>"
ob_refcnt 1 Py_ssize_t
However how I can I get it back to the original C type (zmsg_t *)
Any help really appreciated.
What I've found so far is that I can return the address of the ctypes
object.
msg = Zmsg()
frame = Zframe(b"Hello", 5)
msg.prepend(frame)
return addressof(msg._as_parameter_.contents)
In C I can then cast it back to the original type.
PyObject *pReturn = PyObject_CallObject(pFunc, NULL);
assert(pReturn);
long bla = PyLong_AsLong(pReturn);
zmsg_t* test = (zmsg_t *)bla;
assert(test);
char *hello = zmsg_popstr(test);
assert(hello);
assert(streq(hello, "Hello"));
This works, I'm not sure if this is the right way. It also creates a
complicated setup with the garbage collector.
Anybody better ideas?
You've already got a complicated setup with your ctypes objects...
If you're using the Python C API anyway, why would you use ctypes at
all? You can create custom Python types in C to wrap your C pointers.
Alternatively: if you're using ctypes anyway, why use the Python C API
at all? You can create C function pointers from Python functions with
ctypes.
If you're mixing two different ways of interfacing Python and C, the
result will ALWAYS be messy. Better to stick to one. Personally, I
prefer cffi or cython depending on the situation, as I find them clearer
and easier to use than ctypes. Using the Python C API directly is
usually the hardest to understand and the easiest to get wrong.
-- Thomas
Hi Thomas,
I have an engine running which can call handlers. These handlers return
a zmsg_t (a message) which the engine then can process.
In this engine we have Python embedded and I want to use a Python method
as a handler. To embed Python we need to use the Python C API. To
construct a zmsg_t type in Python we need to call the corresponding C
method and we use ctypes to do that.
I'm using a ctypes binding because it already exists, it's here:
https://github.com/zeromq/czmq/blob/d6283985ba52fd8c3f8fbdc7cd5c08372ff69ca1/bindings/python/czmq/_czmq_ctypes.py#L4392
I know I can use cffi for example but that's IMHO just a ctypes
alternative.
Are you saying it's better to create some approach to create a zmsg_t
using the Python C API?
Please enlighten me if this should be done differently.
Rg,
Arnaud
Ok, you're reply triggered me to do some more reading into the C-API.
I've found I can do it all using the C-API. Especially this guide was
very helpful for my situation:
https://docs.python.org/3/extending/newtypes_tutorial.html
Thnx,
Arnaud
--
https://mail.python.org/mailman/listinfo/python-list