0

I am trying to find simple examples for Py_BuildValue with O& as an argument for reference. Could you please help with any examples or references if any?

Especially the usage of the converter and the value we pass along with this.

I tried a converter function which returns a PyObject* and accepts a void* as input. Unfortunately, this is giving me a seg fault.

Reference: http://web.mit.edu/people/amliu/vrut/python/ext/buildValue.html

Maverickgugu
  • 767
  • 4
  • 13
  • 26
  • Show the code you tried. Make a [mcve]. – Mark Tolonen Jul 18 '23 at 23:46
  • @MarkTolonen I'm trying the example from SWIG using Py_BuildValue for callbacks. http://www.fifi.org/doc/swig-examples/python/callback/widget.i Unfortunately it only supports basic types like integer. I'm trying to get it to work with structures in C. Unfortunately, I'll have to serialize it with O& if I go this route. Do you think its possible to pass an structure object more cleanly for a callback? – Maverickgugu Jul 21 '23 at 12:30

1 Answers1

1

Here's a working example (Windows):

test.c

#include <Python.h>
#include <stdio.h>

#define API __declspec(dllexport)

// Something to validate and convert
struct Example {
    unsigned short magic; // must be 0xAA55
    int a;
    float b;
};

// Return a tuple of (a,b) if magic is valid; otherwise error.
PyObject* converter(void* anything) {
    struct Example* ex = (struct Example*)anything;
    if(ex->magic != 0xAA55) {
        PyErr_SetString(PyExc_ValueError, "invalid Example");
        return NULL;
    }
    return Py_BuildValue("if", ex->a, ex->b);
}

// Use the converter
API PyObject* example(unsigned short magic) {
    struct Example ex = {magic, 1, 2.5};
    return Py_BuildValue("O&", converter, &ex);
}

test.py

import ctypes as ct

# Use ctypes to call the CPython DLL example
dll = ct.PyDLL('./test')
dll.example.argtypes = ct.c_ushort,
dll.example.restype = ct.py_object

print(dll.example(0xAA55))
print(dll.example(0))

Output:

(1, 2.5)
Traceback (most recent call last):
  File "C:\test.py", line 9, in <module>
    print(dll.example(0))
          ^^^^^^^^^^^^^^
ValueError: invalid Example
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251