I am working on a Python code embedding in c++ helloworld program, necessary additional include/library directories are properly set up.
When I use Local Windows Debugger, it shows "Hello World" correctly. But if I double click project.exe, it says project.exe has stopped working.
Does anyone know what kind of configurations or steps to make so that project.exe
shows "Hello World" when double clicked??
Code goes like the following:
main.cpp
#include <iostream>
#include <Python.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
int main()
{
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyObject *pModule = PyImport_ImportModule("helloworld");
PyObject *pFunc = PyObject_GetAttrString(pModule, "printHello");
PyEval_CallObject(pFunc, NULL);
Py_Finalize();
return 0;
}
helloworld.py
def printHello():
print("Hello World!")
Shot in the dark:
you should check the return value of pModule
. My guess is that since you're in a different directory, the import fails, so the PyImport_ImportModule
function returns NULL
(python raises exceptions, but not in this context as this is a C API with its limitations)
This is fragile (and possibly useless):
sys.path.append('./')
You don't know what the current directory is. It would be better to make it relative to the current executable, or configurable with an argument or an environment variable. You could make it relative to the current executable, see Finding current executable's path without /proc/self/exe or Get path of executable
Now, when you try to use this null pointer, the program crashes. Start with this:
PyObject *pModule = PyImport_ImportModule("helloworld");
if (pModule == NULL)
{
std::cout << "could not import module\n";
exit(1);
}
(same goes for the attribute fetch: always protect your calls, or better: wrap them in a C++ method that throws exceptions).
#include <string>
#include <stdexcept>
PyObject *safe_PyImport_ImportModule(const std::string &module_name)
{
PyObject *pModule = PyImport_ImportModule(module_name.c_str());
if (pModule == NULL) // c++11 purists would put "nullptr"
{
std::cout << "cannot import " << module_name << '\n';
throw std::runtime_error("Import error: "+module_name);
}
return pModule;
}