C++ application crashes with embedded Python code - python

I'm trying to run a Python code within a C++ application, based of example from this tutorial. Everything works fine with just running a script:
char filename[] = "D:\\Docs\\Embedding\\bin\\Debug\\load_continiuous_snl_data.py";
FILE* fp;
Py_Initialize();
fp = _Py_fopen(filename, "r");
PyRun_SimpleFile(fp, filename);
Py_Finalize();
But when I try to import script as a module, application crashes
std::vector<int> ExampleData(5);
for(int i=0;i<5;i++)
{
ExampleData[i] = i+1;
}
PyObject *pName,*pModule,*pFunc,*pname;
PyObject *pValue,*pArgs,*pDict;
Py_Initialize();
pName = PyUnicode_FromString("D:\\Docs\\Embedding\\bin\\Debug\\load_continiuous_snl_data.py");
//pModule = PyImport_Import(pname); //running without this line doesn't lead to crashing
Py_Finalize();
I'm using Python 3.7 32bit on Windows. Thanks in advance for any suggestion.

Related

Embedding python in a c program with all dependencies included

I am writing a c application that will let me embed python modules in it. The python modules are responsible for initiating remote procedure calls to python code on remote machine through rpyc library. My python modules will be located in the same place where the application will run from. I am assuming that my c application will run on a machine that does not have the needed python libraries e.g rpyc. I wanted to know if there is a way I can bundle all the dependencies together with my modules when I ship the code for distribution.
I have used cython to compile the python module to .pyd but still this needs the required python libraries installed.
My c code;
int main(){
int argc = 2;
wchar_t* argv[] = { (wchar_t *)"mypythonmodule", (wchar_t *)"-h", NULL };
const char *module = argv[0];
PyObject *pName, *pModule, *pFunc;
PyObject *pArgs, *pValue;
Py_Initialize();
pName = PyUnicode_DecodeFSDefault(module);
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule != NULL) {
pArgs = PyTuple_New(argc);
for (int i = 0; i < argc; i++) {
pValue = PyUnicode_FromString(argv[i]);
PyTuple_SetItem(pArgs, i, pValue);
}
pFunc = PyObject_GetAttrString(pModule, "parse_args");
PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pFunc);
Py_DECREF(pArgs);
//Py_DECREF(pValue);
Py_Finalize();
}
}

embedding python in c++: python script not recognized

I am trying to embed python script into c++ project.
Below is what I have tried so far.
#include<iostream>
#include <Python.h>
int
main()
{
Py_Initialize();
PyObject* sysPath = PySys_GetObject("path");
PyObject* modPath = PyBytes_FromString("C:\\Users\\naal\\Documents\\Visual Studio 2017\\Projects\\Project1\pyscripts");
int result = PyList_Insert(sysPath,0, modPath);
PyObject *pModule = PyImport_ImportModule("myscript2");
printf("%p\n", pModule);
return 0;
}
below is the python script "myscript2.py"
def find_me():
print("hey you found me")
The problem is, the main module is not able to find the python script i.e object pyModule is always NULL, no matter how I change python script path.
What am I doing wrong ?
I ended up implementing this in another way.
#include<iostream>
#include <Python.h>
int main() {
std::string location = "C:\\Users\\myscript.py";
const char* file_location = location.c_str(); FILE* file_pointer;
Py_Initialize();
file_pointer = _Py_fopen(file_location, "r");
PyRun_SimpleFile(file_pointer, file_location);
Py_Finalize();
return 1;
}
The above seemed to work. I still don't know why the SYSPATH idea originially mentioned in the question didn't work.

Embedding python in c++: Segmentation fault [duplicate]

This question already has an answer here:
Embedded Python 2.7.2 Importing a module from a user-defined directory
(1 answer)
Closed 5 years ago.
I am remote Debugging a c++ application with Visual studio on a linux device (raspberry pi/raspbian). In this c++ application I embedded a simple Python script by loading the function using the Python/c api. This is my c++ Code:
#include <Python.h>
int main(int argc, char* argv[])
{
PyObject *pName, *pModule, *pDict, *pFunc, *pValue;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyUnicode_FromString("//home//pi//projects//InfoBeam//WebScraperPython.txt");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, "pyMain");
if (PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, NULL);
}
else
{
PyErr_Print();
}
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
return 0;
}
The Problem is, that I get a segmantation fault while running the function PyModule_GetDict(pModule). What am I doing wrong? This is the error message:
Program received signal SIGSEGV, Segmentation fault.
0x76bfdd28 in PyModule_GetDict () from /usr/lib/arm-linux-gnueabihf/libpython3.5m.so.1.0
Segmentation fault
EDIT: Okay, pModule was indeed NULL, probably because PyUnicode_FromString failed. Since PyImport_Import is failing: Where do I Need to save my Script, or: how do I pass the api the info where it is?
Before calling PyModule_GetDict, check that pModule isn't NULL. It would mean that PyImport_Import failed to import the module (problem with path, etc...)

PyImport_Import fails (returns NULL)

I am a newbie in python, so may be this is a silly question. I want to write simple c program with embedded python script. I have two files:
call-function.c:
#include <Python.h>
int main(int argc, char *argv[])
{
PyObject *pName, *pModule, *pDict, *pFunc, *pValue;
if (argc < 3)
{
printf("Usage: exe_name python_source function_name\n");
return 1;
}
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
if ((pName = PyString_FromString(argv[1])) == NULL) {
printf("Error: PyString_FromString\n");
return -1;
}
// Load the module object
if ((pModule = PyImport_Import(pName)) == NULL) {
printf("Error: PyImport_Import\n");
return -1;
}
// pDict is a borrowed reference
if ((pDict = PyModule_GetDict(pModule))==NULL) {
printf("Error: PyModule_GetDict\n");
return -1;
}
...
and
hello.py:
def hello():
print ("Hello, World!")
I compile and run this as follows:
gcc -g -o call-function call-function.c -I/usr/include/python2.6 -lpython2.6
./call-function hello.py hello
and have this:
Error: PyImport_Import
i.e. PyImport_Import returns NULL. Could you help me with this issue? Any help will be appreciated.
Best wishes,
Alex
I have resolved this issue by setting PYTHONPATH to pwd. Also module name (without .py) should be set for argv[1].
Thank you!
I ran into this issue also after struggling for a while.After searching the web I found that is was a system path issue. After adding the two lines after Py_Initialize(); it worked.
OS: Windows 7, Compiler: Embarcadero C++ Builder XE6, Python: Version 2.7
Reference: C++ With Python
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\"C:\\Python27\")");
If the python source file is located in the working directory (i.e. where the *.cpp files of the project reside), you can use...
PyRun_SimpleString("sys.path.append(os.getcwd())");
...to add the working directory to the Python path.
This is an obscure case but my python function was importing code that required argv to be set. In order to fix that I had to add:
PySys_SetArgv(argc, argv);
after the Py_Initialize() call and it started working.

Why do I need to explicitly add os.getcwd() to sys.path when importing Python scripts from a C application?

I was going through the Python documentation regarding Extending Python with C/C++, and I found a very interesting scenario. Consider that I have the following, trivial Python script named test_script.py in my working directory:
import time
def My_Python_Func():
print "My_Python_Func() Called: " + str(time.time())
In the same directory, I have a file called another_test_script.py, which has:
import test_script
test_script.My_Python_Func()
Which works fine, when called as python ./another_test_script.py. Now, I'm trying to call said function from a C environment linked with the Python libraries as follows:
#include <stdio.h>
#include <Python.h>
PyObject *pName, *pModule, *pDict, *pFunc, *pVal;
int main()
{
const char* script_name = "test_script";
const char* func_name = "My_Python_Func";
Py_Initialize();
pName = PyString_FromString(script_name);
PyRun_SimpleString("import os");
PyRun_SimpleString("import sys");
/* * * * IF I COMMENT THE FOLLOWING LINE OUT, pModule IS ALWAYS SET TO NULL * * * */
PyRun_SimpleString("sys.path.insert(0, os.getcwd())");
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule != NULL)
{
pFunc = PyObject_GetAttrString(pModule, func_name);
}
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, func_name);
if (PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, NULL);
Py_DECREF(pModule);
Py_DECREF(pName);
}
else
{
PyErr_Print();
}
Py_Finalize();
return 0;
}
As noted in the comments in the above C program, commenting out the line containing PyRun_SimpleString("sys.path.insert(0, os.getcwd())") causes the call to PyImport_Import to fail (returning NULL). Furthermore, calling PyRun_SimpleString("import test_script") appears to behave the same way.
Why do I need to manually add the current working directory to Python's sys.path list of strings, when simply importing it from another Python script in the same working directory? Furthermore, why does Python not search the current working directory in the first place (as os.getcwd() returns the correct path)? Is this an appropriate solution, if I wish to import functions from scripts bundled with my C application?
Adding the script directory to sys.path is a peculiarity of the python executable; it is not done by default when the interpreter is initialized, since it is not always appropriate to do so in embedded applications.

Categories