I have the following code in Python, which uses pyjexl module:
import pyjexl
jexl = pyjexl.JEXL()
jexl.add_transform("lowercase", lambda x: str(x).lower())
I want to do the same using Python C API. Something like this:
Py_Initialize();
PyObject* pyjexlModule = PyImport_ImportModule("pyjexl");
PyObject* jexl = PyObject_CallMethod(pyjexlModule, "JEXL", NULL);
const char* myLambda = "lambda x: str(x).lower()";
PyObject* lambda = ... /* something using myLambda */
PyObject_CallMethod(jexl, "add_transform", "sO", "lowercase", lambda);
(Simplified version of the code, e.g., NULL checking and Py_XDECREF() have been omitted)
The problem I'm trying to solve is how to get a PyObject representing a lambda function which Python code is contained in the C-string myLambda.
How can I achieve this?
I have tried with the suggestion by @DavidW using this:
PyObject* globals = PyDict_New();
PyObject* locals = PyDict_New();
PyObject* lambda = PyRun_String(myLambda, Py_eval_input, globals, locals);
But I think it's not working, as the resulting lambda variable (inspected using debugger) is of type PyNone:

PyRun_String:where
some_dictcan be an empty dict. (I think on some older versions of Python you'd need to havestrin the dict, so might need to usePyEval_GetBuiltinsbut this should be unnecessary now).The exact function I tested with was
Note that I've omitted error handling for
PyDict_New()- ideally there should be a NULL check after each of these.In order to test it I built it into a Cython module - that's just because it provides an easy way to compile and call C functions so it's a quick way to test it:
The Cython module is compiled with
cythonize -if modulename.pyxYou can then test it with
The second line returns
<function <lambda> at 0x7f72c0d8bc40>(the exact address of the lambda will vary of course).