Hy Developers,
How can i call a python function inside C++? I found a closed issue (https://github.com/pybind/pybind11/issues/30) where this question was asked by @skebanga but it seems that his question was not fully answered.
For example: I have a python function myfun
def myfun(i, j):
out = i + j
return out
Now i would like to call this function inside visual studio 2015. How can i do this? :P
I read the docs and tried to figure out how the test_callbacks.cpp/test_callbacks.py works but i really dont get it. Is there somewhere else a simple example how to do this?
Thank you for your help!
pybind11 doesn't officially support embedding python in C++ (or didn't when I last looked at it)
However, it is possible.
I wrote a blog post about doing this which might be helpful to you.
Please note I would suggest reading this blog post first, as it gives context to the other one. (It's about embedding python using boost::python)
All that said, you might want to consider using boost::python, where embedding is supported.
HTH
Ok thanks for this information! :)
But whats about this test_callbacks.cpp/test_callbacks.py examples in tests directory? I thought this example would deal with that question? See http://pybind11.readthedocs.io/en/master/advanced/pycpp/object.html
The documentation mentions the following but doesn't mention how to get a function.
Calling Python functions
It is also possible to call python functions via operator().
py::function f = <...>;
py::object result_py = f(1234, "hello", some_instance);
MyClass &result = result_py.cast
I'm doing the following and it just keeps crashing (due to it attempting to access something 8 bytes into a structure that pointed to by a null pointer):
PyObject* myFunc = PyObject_GetAttrString(myModule, "PrintObject");
if (myFunc == nullptr) {
PyErr_Print();
return 0;
}
printf("%p\n", (void*)myFunc);
py::object func = py::cast(myFunc);
func();
I need to be able to call into Python and pass C++ instantiated objects to embedded Python, where Python can then use to set and get properties on those objects.
You could do this as follows:
auto module = py::reinterpret_borrow<py::object>(myModule);
auto myFunc = module.attr("PrintObject");
myFunc(<arguments>);
By the way: if you're going to let out your frustration here, then please do use Boost.Python instead. This is a free product developed by volunteers, and nobody is forcing you to use it.
Sorry, I removed my frustration from the comment. It has been a very trying day for me and I'm racing to finish this for a deadline and let it get the better of me.
Thanks for the response this is now working for me:
salah@Europa:~/Enlistments/scratch2/testpythoninterface$ ./pythontest
Bob
auto module = py::reinterpret_borrow<py::object>(myModule);
auto myFunc = module.attr("PrintObject");
Pet myPet("Bob");
myFunc(myPet);
with the following python code:
import pythontest
def PrintObject(object):
print(object.getName())
You might also get myModule as a py::module directly (i.e. instead of as a raw CPython pointer) with auto myModule = py::module::import("package");, in which case you don't need the reinterpret_borrow.
(For pretty much all common things, it shouldn't be necessary to touch the C API directly).
Thanks, I switched over to that for the module and it's now working.
I still seem to need to do this to get it to find the module though:
PyRun_SimpleString("import sys\nimport os\nsys.path.insert(0,os.getcwd())\n");
Is there some other way I could do so?
Untested, but I think you could use:
py::reinterpret_borrow<list>(PySys_GetObject("path")).append(".");
or you could also import both via py::module::import and do the equivalent without touching the C API.
I suggest to move further discussion to Gitter, since this is not a pybind11 bug.
Looks like this issue has been resolved here. In addition, #774 should resolve issues with embedding support and the new documentation page includes a specific example of calling a Python function in C++.
@Salahuddin-Khan
hey you said that below is working for you.
auto module = py::reinterpret_borrow<py::object>(myModule);
auto myFunc = module.attr("PrintObject");
could you please tell me how you include that python file into the main program?
p.s im new here
In my case, the python module is being used for a plug in. I initialize it as follows:
The PlugInModuleName is the name of the python module that is actually utilized. I have some initialization code that adds the path to the plug-in module so that it can be found during initialization.
void CPythonInterface::InitializePlugIn(std::string PlugInPath, std::string PlugInModuleName)
{
std::string plugInInitCode;
Py_Initialize();
pybind11_init();
plugInInitCode = "import sys\nimport os\nsys.path.insert(0,\"";
plugInInitCode += PlugInPath;
plugInInitCode += "\")";
PyRun_SimpleString(plugInInitCode.c_str());
m_Module = module::import(PlugInModuleName.c_str());
m_InvokePlugIn = (py::function) m_Module.attr("InvokePlugIn");
m_Initialized = true;
}
The actual invocation code is similar to this:
void CPythonInterface::InvokePlugIn(TaskInformation* Task,
std::string PlugInName,
PlugInOperation::Type OperationType,
IInterfacePlugInData* Data)
{
m_InvokePlugIn(Task, PlugInName.c_str(), OperationType, Data->GetTargetName().c_str(), Data);
}
I hope this helps.
-s
@Salahuddin-Khan
Thanks alot for the help, i got it working.
cheers!
Hi,
I have a similar question. I have a usecase where I have implemented an API in python and it needs to return struct, vector or map to C++. Could you please help me with an example how to do that. All the usecases I see in pybind is just simply python being embedded in C++ without any return value.
I am in a time-bound project and looking forward to quick responses.
You could do this as follows:
auto module = py::reinterpret_borrow<py::object>(myModule); auto myFunc = module.attr("PrintObject"); myFunc(<arguments>);By the way: if you're going to let out your frustration here, then please do use Boost.Python instead. This is a free product developed by volunteers, and nobody is forcing you to use it.
@wjakob Is it possible to pass the pointer of the C++ data type to the loaded modules
(for ex; std::vector
Thank you
Most helpful comment
You could do this as follows:
By the way: if you're going to let out your frustration here, then please do use Boost.Python instead. This is a free product developed by volunteers, and nobody is forcing you to use it.