Closed NiKeYiGuN closed 1 year ago
There's nothing that can be done automatically in the above as-is. Even looking at it, I have to guess what is intended here, which is a standard problem with void*
(or any low-level code for that matter).
Two rather different things I can think off on the top of my head of what that code possibly intended ...
C++ function pointer, so an example would be:
import cppyy
cppyy.cppdef(r"""\
double cpp_func(double (*l)(double)) {
return l(2.);
}""")
python_lambda = lambda a: a*a
print(cppyy.gbl.cpp_func(python_lambda))
(Note that in the above example, Python remains responsible for the python_lambda
lifetime: C++ does not take ownership.)
Or perhaps the lambda should be passed as-is:
import cppdef
cppyy.cppdef(r"""\
#include "Python.h"
PyObject* py_func(PyObject* l) {
PyObject* py2 = PyFloat_FromDouble(2.);
PyObject* res = PyObject_CallFunctionObjArgs(l, py2, NULL);
Py_DECREF(py2);
return res;
}""")
python_lambda = lambda a: a*a
print(cppyy.gbl.py_func(python_lambda))
Or??
If you're dealing with 3rd party code, you can always wrap the C++ function to make the typing clear, with the wrapper passing subsequently passing the result through as a void*
.
Thanks!
I think I know what I'm going to do. void cpp_func(void *d);
python_lambda = a: a*a
cppyy.gbl.cpp_func(python_lambda) cpp_func is not modifiable
But lambada expressions may be of a different form, for example, there may also be : python_lambda = a,b: a*a+b or others
I don't really want to modify the C++ code unless I have to, and I'm wondering if there's a way to accept any expressions。 Thank you very much for your patient answer, I will use cppyy for a long time, and I hope it will be of some help to cppyy in the future
I'm wondering if there's a way to accept any expressions
With templates and proper annotation, yes, otherwise PyObject*
(as per above) is as generic as it gets. The problem you'll have with void*
though, is that you can't do anything with it on the C++ side (unless you e.g. pre-compile a range of possible options).
Template example:
import cppyy
cppyy.cppdef(r"""\
void cpp_func2(void* l) {
std::cerr << "received: " << l << std::endl; // what to do with `l` here?
}""")
python_lambda = lambda a: a*a
# use a std::function template to construct a typed signature
f = cppyy.gbl.std.function['double(double)'](python_lambda)
print(f(2.)) # fine to use directly
cppyy.gbl.cpp_func2(f) # works, but there's nothing to be done with `f` on the C++ side ...
with 'l' that to do:
`import cppyy
cppyy.cppdef(r""" typedef double (cpp_func)(double u, void f);
class B{ private: cpp_func f; void *d
B(cpp_func f, void *d): f(f),d(d){}
void a(){ double c=1; f(a, d) } } double func(double u, void f) { PyObject func = (PyObject )f; PyObject d = PyFloat_FromDouble(u); PyObject *pyret = PyObject_CallFunctionObjArgs(func, d, NULL); return pyret }""")
python_lambda = lambda a: a*a cppyy.gbl.B(cppyy.gbl.func, python_lambda )`
Still not 100% sure what you're after, but to make the above code work, would be probably take something like this:
import cppyy
cppyy.cppdef(r"""\
#include "Python.h"
void* castpy(PyObject* pyobject) { return (void*)pyobject; }
typedef double (*cpp_func)(double u, void* f);
class B {
cpp_func f;
void* d;
public:
B(cpp_func ff, void* d) : f(ff), d(d) {}
double a(double u) {
return f(u, d);
}
};
double func(double u, void* f) {
PyObject* func = (PyObject*)f;
PyObject* d = PyFloat_FromDouble(u);
PyObject* pyret = PyObject_CallFunctionObjArgs(func, d, NULL);
Py_DECREF(d);
double ret = PyFloat_AsDouble(pyret);
Py_DECREF(pyret);
return ret;
}""")
python_lambda = lambda a: a*a
b = cppyy.gbl.B(cppyy.gbl.func, cppyy.gbl.castpy(python_lambda))
print(b.a(2.))
OK,Thanks, that's exactly the answer I was looking for.
in C++ void cpp_func(void *d);
python_lambda = a: a*a
cppyy.gbl.cpp_func(python_lambda)
Can give me any advice on how I should do this? Thanks!