thierry-martinez / pyml

OCaml bindings for Python
BSD 2-Clause "Simplified" License
182 stars 31 forks source link

pass PyObject * to C function #90

Open dlindsaye opened 1 year ago

dlindsaye commented 1 year ago

Great job with this package!

I'm using Dl.dlopen from the ctypes.foreign package to load a collection of C functions which use the Python C API. As such, coming from OCaml and pyml, I need a way to call a C function and pass it a naked PyObject * . If I use Pycaml.pyunwrap_value I get a type error.

More specifically, I have:

 Py.initialize ();
 let globals = Py.Module.get_dict (Py.Module.main ()) in
 let open Ctypes in
 let c_set_item = Dl.(dlopen ~filename:"c_py_set_item.so" ~flags:[RTLD_NOW]) in
 let my_set_item_int = Foreign.foreign ~from:c_set_item "my_set_item_int" (ptr void @-> string @-> int @-> returning void) in
 let _ = my_set_item_int (Pycaml.pyunwrap_value globals) "my_variable" 4 in

and the following mundane C code:

#include <Python.h>

void
my_set_item_int(PyObject *obj, char *var_name, int n)
{
    PyObject *value = Py_BuildValue("%d", n);
    PyDict_SetItemString(obj, var_name, value);
}

This yields the error pyml_unwrap_value: type mismatch from within pyml_stubs.c as the extracted pointer is coming from the wrong type of Python capsule.

Any suggestions on how to get this to go through? Should I be using something other than Pycaml.pyunwrap_value?