An aricle by Jum Du at CodeProject (see: http://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I) gives a very detailed overview of how to call a Python function from C/C++ routines in an embedded interpreter using CPython interface. While this quite useful, however, one needs to keep the .py file at the same place where the C/C++ executable resides.
I needed a solution where the .py file could reside anywhere on the local file system. Turns out that the modification is quite simple, you just need to make sure that sys.path is appended with the correct path at runtime where the .py file can be found. The follwing is the pseudo(C++)-code of how I do this:
PyObject* runFunction(std::string scriptFilePath, std::string funcName, PyObject *arglist)
{
// this code is based on http://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I
try {
PyObject *pName, *pModule, *pDict, *pFunc, *pValue = Py_None;
std::string thePath = // .. your code to extract the path, for '/home/ganeshv/pyfiles/my.py' : path is '/home/ganeshv/pyfiles/'
std::string theModule = // .. your code to extract the module, for '/home/ganeshv/pyfiles/my.py' : module is 'my'
// printf("importing [%s] from [%s]\n", theModule.c_str(), thePath.c_str());
// first extract the file name and file path
std::string code = "sys.path.append(\"" + thePath + "\")\n";
// add the path
PyRun_SimpleString(code.c_str());
// Build the name object
pName = PyString_FromString(theModule.c_str());
if (pName == Py_None) return Py_None;
// Load the module object
pModule = PyImport_Import(pName);
if (pModule == Py_None) {
Py_DECREF(pName);
return Py_None;
}
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
if (pDict == Py_None) {
Py_DECREF(pModule);
Py_DECREF(pName);
return Py_None;
}
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, funcName.c_str());
if (PyCallable_Check(pFunc)) {
pValue = PyObject_CallObject(pFunc, arglist);
} else {
PyErr_Print();
} // end if
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
return pValue;
} catch(...) {
return Py_None;
}
}
I needed a solution where the .py file could reside anywhere on the local file system. Turns out that the modification is quite simple, you just need to make sure that sys.path is appended with the correct path at runtime where the .py file can be found. The follwing is the pseudo(C++)-code of how I do this:
PyObject* runFunction(std::string scriptFilePath, std::string funcName, PyObject *arglist)
{
// this code is based on http://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I
try {
PyObject *pName, *pModule, *pDict, *pFunc, *pValue = Py_None;
std::string thePath = // .. your code to extract the path, for '/home/ganeshv/pyfiles/my.py' : path is '/home/ganeshv/pyfiles/'
std::string theModule = // .. your code to extract the module, for '/home/ganeshv/pyfiles/my.py' : module is 'my'
// printf("importing [%s] from [%s]\n", theModule.c_str(), thePath.c_str());
// first extract the file name and file path
std::string code = "sys.path.append(\"" + thePath + "\")\n";
// add the path
PyRun_SimpleString(code.c_str());
// Build the name object
pName = PyString_FromString(theModule.c_str());
if (pName == Py_None) return Py_None;
// Load the module object
pModule = PyImport_Import(pName);
if (pModule == Py_None) {
Py_DECREF(pName);
return Py_None;
}
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
if (pDict == Py_None) {
Py_DECREF(pModule);
Py_DECREF(pName);
return Py_None;
}
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, funcName.c_str());
if (PyCallable_Check(pFunc)) {
pValue = PyObject_CallObject(pFunc, arglist);
} else {
PyErr_Print();
} // end if
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
return pValue;
} catch(...) {
return Py_None;
}
}
No comments:
Post a Comment