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