Embedding python 3.4 into C++ Qt Application? - python

I'm making an Qt Quick GUI application(for windows), which uses OpenGL and C++ for some computationally intensive stuff. I want to embed python code into the app, for doing some stuff which is comparatively easier in python.
Basically, I just want the c++ code to call a function in a python script and let the script do the job, then store the returned data in a variable(string, or float etc.) for further use. I'm using Qt creator, and I got python3 lib for MinGW compiler. I tried some code, but its looks like python lib is not quite compatible with Qt creator. IS using pyqt for this will be a good idea? What will be the best and easiest way to do this ?
EDIT: This is the basic code I tried, first it gave me an error saying, cannot find pyconfig.h. Then I added an INCUDEPATH to my python34 include directory.
#include "mainwindow.h"
#include <QApplication>
#include <boost/python.hpp>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
using namespace boost::python;
PyObject *pName, *pModule, *pDict, *pFunc, *pValue;
Py_Initialize();
pName = PyString_FromString(argv[1]);
pModule = PyImport_Import(pName);
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, argv[2]);
if (PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, NULL);
} else
{
PyErr_Print();
}
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
Py_Finalize();
return a.exec();
}
My .pro file:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = TestWidgetApp
TEMPLATE = app
INCLUDEPATH += C:/boost_1_57_0
INCLUDEPATH += C:/Python34/include
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
OTHER_FILES +=
Then the following errors:
C:\Python34\include\object.h:435: error: C2059: syntax error : ';'
C:\Python34\include\object.h:435: error: C2238: unexpected token(s) preceding ';'
C:\Users\Amol\Desktop\TestWidgetApp\main.cpp:19: error: C3861: 'PyString_FromString': identifier not found

The problem here is that Python 3.4 has a struct member called "slots", (file object.h, in the typedef for PyType_Spec), which Qt defines out from under you so that you can say things like:
public slots:
in your code. The solution is to add:
#undef slots
just before you include Python.h, and to redefine it before you include anything that uses "slots" in the way that Qt does:
#undef slots
#include <Python.h>
#define slots
#include "myinclude.h"
#include <QString>
A bit of a hack (because you're depending on a particular definition of slots in Qt), but it should get you going.

I have removed all the Qt code from your example and then I tried to compile it (Qt has nothing to do with your compile error). And it compiles for me. The difference was I used the include files from Python 2.7.
So I did a little search for the string PyString_FromString in the folders: C:\Python33\includes (I noted you use python 3.4 and not 3.3 but I suspect this is a 3.x thing) and C:\Python27\includes.
Results:
Python 3.3
Python 2.7
So, apparently, Python 3.4 is not supported by your BoostPython version.

Python3 has no PyString_FromString function. Python3 str type internally is unicode objects with complex structure.
Use PyUnicode_FromString or PyUnicode_FromStringAndSize for constructing str object from UTF-8 encoded C string (char*).

Move your
#include "boost/python.hpp"
...to be before your other includes and it will resolve your problem.
The actual issue is as Scott Deerwester described in his answer.

Related

Using pybind11 within C++ in JUCE Framework

I'm trying to read a string list output from a Python script, in order to pass it to a JUCE MainComponent (written in C++).
The code is the following (which is a starting one, just to test the pybind library):
#include <pybind11/embed.h>
#include <pybind11/pybind11.h>
namespace py = pybind11;
MainComponent::MainComponent()
{
auto math = py::module::import("math");
auto resultobj = math.attr("sqrt")(2);
double result = resultobj.cast<double>();
}
However, I always encounter the following error:
_PyRuntime.gc.**generation0** was nullptr.
Any suggestions? Thanks in advance
You have to first initialize the Python interpreter, like this:
MainComponent::MainComponent()
{
py::scoped_interpreter guard{};
auto math = py::module::import("math");
auto resultobj = math.attr("sqrt")(2);
double result = resultobj.cast<double>();
}
You also have to link with the needed python libraries. In CMake, this means adding
target_link_libraries(your_target PRIVATE pybind11::embed)
to your CMakeLists.txt file.

C++ Boost::Python Py_Initialize throwing Assertion Failed on object.c

I am trying to embed the Python 3.5 interpreter in a C++ program with Boost 1.76.0. While doing this, I am having issues as the program throws an assertion failed at the Py_Initialize();
Assertion failed: (op->_ob_prev == NULL) == (op->_ob_next == NULL), file ..\Objects\object.c, line 84
The minimal code in which this happens is as follows:
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python.hpp>
#include <Python.h>
int main(int argc, char** argv)
{
try
{
Py_Initialize();
}
catch (boost::python::error_already_set& e)
{
PyErr_PrintEx(0);
return 1;
}
return 0;
}
Looking online I found other few occurrences with no answers tho. Any ideas why this is happening?
As it turns out, the include order is important. I could not find any notes on this on the Boost documentation and examples, so I will add this here: putting the #include <Python.h> before the #include <boost/python.hpp> fixed the issue for me.
If anyone has some insight on how this happens, please feel free to add more details.
I also found this (C++ including python.h and boost/python.hpp causes SEH exception) so I don't know if I am just lucky it works, if this has been fixed in later versions of Boost or something else.
Update 1: Trying to just remove #include <Python.h> causes the error to present itself again. Is this a Boost bug/compilation issue?
Update 2: I have indeed incountered an issue as said in the aforementioned question, in particular when importing a python script. So I am back to mile 0, does anyone have any ideas?
Update 3: I tried to use precompiled DLLs, use other versions of Python, but I still keep getting this issue. I am really at a loss of ideas.

Unable to import Python module written in C

I have been trying to work out how to make a .pyd (Python Extension Module) file from a C script (without swig or anything else except MinGW) and have successfully built it into a .pyd.
The problem however occurs when I try and import the module.
If I run it the module runs successfully (as far as I can see) and then an error appears saying Python Has Stopped Working and it closes without executing the rest of the program.
Here is my C script (test.c):
#include <python.h>
int main()
{
PyInit_test();
return 0;
}
int PyInit_test()
{
printf("hello world");
}
And Python Script (file.py):
import test
print('Run From Python Extension')
I compiled the script with:
gcc -c file.py
gcc -shared -o test.pyd test.c
I can't find any errors when compiling in command prompt and am using python 3.6 (running on Windows 10).
I can't find much on the subject and would prefer to keep away from Cython (I already know C) and Swig.
Any help to tell me what is wrong would be fantastic.
Creating a Python extension is completely different than writing regular C code. What you have done is simply creating a valid C program but that doesn't make sense for Python.
That's how your program should look like (it's just a skeleton, not the proper, working code):
#include <Python.h>
#include <stdlib.h>
static PyObject* test(PyObject* self, PyObject* args)
{
printf("hello world");
return NULL;
}
static PyMethodDef test_methods[] = {
{"test", test, METH_VARARGS, "My test method."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC init_test_methods() {
Py_InitModule("test", test_methods);
}
int main(int argc, char** argv)
{
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
init_test_methods();
}
I recommend you read more about this at the following link: http://dan.iel.fm/posts/python-c-extensions/ as well as in the official docs.

Including 3rd party python module in c++ application

I am trying to build an application to parse netCDF4 files in c++.
What I have done:
Succeeded in parsing the files in python scripts.
What I need help with:
Including my python script as a module. When I run my C++ program it complains that it can't access numPy.
What I Know:
I fixed the same issue with the netCDF4 by copying the netCDF4.pyd file where my c++ executable was located, but cannot find the numPy. equivalent.
Thanks for any suggestions.
Welcome to the community! I hope I understand the question correctly - is it importing a python module into c++? If that is so, try the following tutorial: Embedding Python in C/C++: Part I.
Basically, to paraphrase, DON'T use code conversion or translation - it is unnecessairly complex. Just make the python code communicate with the C code as follows. Kudos to website above for the code, comments by me.
#include <Python.h> //get the scripts to interact
int main(int argc, char *argv[])
{
PyObject *pName, *pModule, *pDict, *pFunc, *pValue; //Arguments that are required.
if (argc < 3)
{
printf("Usage: exe_name python_source function_name\n");
return 1;
}
// Allow your program to understand python
Py_Initialize();
// Initialize Name
pName = PyString_FromString(argv[1]);
// Import the module from python
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// same situiation as above
pFunc = PyDict_GetItemString(pDict, argv[2]);
if (PyCallable_Check(pFunc))
{
PyObject_CallObject(pFunc, NULL);
} else
{
PyErr_Print();
}
// Tidy Everything Up.
Py_DECREF(pModule);
Py_DECREF(pName);
// End interpreter
Py_Finalize();
return 0;
}
I suggest you read the above tutorial, though.
Hope this helps!

Embedding Python into C

Win7 x64, Python3.3 32bit, Visual Studio 2010/2012 (same behavior). The following code compiles and runs just fine (i.e. prints current date):
extern "C"{ // not having it doesn't make any difference either
#include <Python.h>
}
int main() {
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
Py_Finalize();
return 0;
}
while this here fails with a MessageBox saying The application was unable to start correctly (0xc0000005). Click OK to close the application. before main executed (so no breakpoint possible).
extern "C"{ // not having it doesn't make any difference either
#include <Python.h>
}
int main() {
Py_Initialize();
PyObject *p = PyUnicode_FromString("test");
Py_Finalize();
return 0;
}
So the problem seems to have been the following: I was linking with python3.lib but since the string functions were completely overworked with Python3.3 there seemed to have been some problem with correctly linking them. (can't really explain why this would be so, since PyUnicode_FromString existed obviously in earlier versions of python3 too).
Why I couldn't get a useful error message about that fact is also beyond me, but there we go: linking against python33.lib solved the problem perfectly.
I think this could be for 2 reasons, but I'm pretty sure its this one:
http://docs.python.org/2/c-api/unicode.html
You need to null terminate y our constant string "test" by making it "test\0". If that doesn't work, it might have to do with the fact that c files are ansi and not utf8.
Your broken program is linking against a build of Python that uses UCS-2 as the internal unicode representation, but the installed Python uses UCS-4, and therefore the PyUnicodeUCS2_* imports can't be resolved. You'll need to link against the UCS-4 build instead.

Categories

Resources