Embedding Python within C++ (CPython API) - python

I'm trying to embed Python within my C++ project (Qt5). My project looks like this:
python_test.pro:
QT += core
QT -= gui
TARGET = python_test
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
INCLUDEPATH += C:\Tools\Python\Python35_64\include
LIBS += -LC:\Tools\Python\Python35_64\ -lpython3
main.cpp:
#include <Python.h>
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
Py_Finalize();
return a.exec();
}
When compiling I get a linker error telling me this: main.cpp:-1: Error: undefined reference to `__imp_PyRun_SimpleStringFlags'.
The funny thing is that Py_Initialize() and Py_Finalize() can be found. I read something about the define Py_LIMITED_API which hides the function PyRun_SimpleStringFlags. But I don't get it.
How am I supposed to run a Python script/file/string without these functions being available within the C API?
Setup:
Win7 Prof 64 bit
Qt 5.5.1
g++.exe (Rev1, Built by MSYS2 project) 5.3.0
Python 3.5.1 64-bit (prebuilt from https://www.python.org/downloads/release)/python-351/)

I tested this on my computer (without Qt though), with -lpython35 compiling succeeded and with -lpython3 it did not.
So
LIBS += -LC:\Tools\Python\Python35_64\ -lpython35
instead of
LIBS += -LC:\Tools\Python\Python35_64\ -lpython3

Related

Can't link Python libraries inside C program

I want to run a basic python script inside a C program using Eclipse. This is the code:
#include <Python.h>
int main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
return 0;
}
I am trying to link to several shared libraries like libpython2.7.so in Eclipse linker settings but I always get this error:
Invoking: GCC C Linker
gcc -L/usr/lib/x86_64-linux-gnu/ -o "Test" ./src/Test.o -llibpython2.7
/usr/bin/x86_64-linux-gnu-ld: cannot find -llibpython2.7
collect2: error: ld returned 1 exit status
I can't find any tutorial with the name of the lib that should be linked.
Typically -l doesn't require the lib prefix or the .so suffix...
Try using -lpython2.7 instead of -llibpython2.7.

Qt: Undefined symbols when trying to use python.h in qt

I am doing some tiny work with Qt on Mac. I need to call a python function in my main function. But when I try to call Py_initialize() as everyone said, compiler throws a error like this:
Undefined symbols for architecture x86_64:
"_Py_Initialize", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
make: *** [video.app/Contents/MacOS/video] Error 1
07:48:07: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project video (kit: Desktop Qt 5.8.0
clang 64bit)
When executing step "Make"
My code is trivial and there should not be anything weird about this. Here it is:
// bunch of headers
#include <python2.7/Python.h>
using namespace std;
int main(int argc, char *argv[])
{
Py_Initialize();
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:///main.qml")));
QObject *object = component.create();
QObject *mainForm = object->findChild<QObject*>("mainForm");
SignalNexus sn;
QObject::connect(mainForm, SIGNAL(populateToken(QString)), &sn, SLOT(pushToPipe(QString)));
QObject::connect(&sn, SIGNAL(populateResult(QVariant, QVariant)), mainForm, SLOT(handleResult(QVariant, QVariant)));
return app.exec();
}
When I comment the Py_initalize() line, everything works fine. I figure that this is something to do with OSx. But I really don't know how to fix this thing. Help needed.
Change your include line to this
// bunch of headers
#include <Python/Python.h>
using namespace std;
int main(int argc, char *argv[])
{
Py_Initialize();

possible to compile python.exe without Visual Studio, with MinGw

I am trying to achieve things laid out on this page:
https://blogs.msdn.microsoft.com/pythonengineering/2016/04/26/cpython-embeddable-zip-file/
The code I am trying to compile is just this:
#include "Python.h"
int
wmain(int argc, wchar_t **argv)
{
return Py_Main(argc, argv);
}
In VisualStudio 15 I have to add the python/include and link to the python libs directories in the project and also add:
#include "stdafx.h"
and then it compiles and works fine. I'm just curious, is it possible to do this with mingw, or another open source C/C++ compiler?
If I place a file my_python.cpp which contains the following:
#include "include/Python.h"
int
wmain(int argc, wchar_t **argv)
{
return Py_Main(argc, argv);
}
in the root directory of a fresh 32-bit python 3.5 install (windows 7 x64), cd to that directory and try to run:
gcc my_python.cpp -Llibs -lpython35 -o my_python.exe
I get this error:
c:/mingw/bin/../lib/gcc/mingw32/5.3.0/../../../libmingw32.a(main.o):(.text.startup+0xa0): undefined reference to `WinMain#16'
Any way to fix this, get it running without Visual Studio?
The error is unrelated to Python. wmain is Visual Studio specific. GCC does not treat wmain as entry point, it just sits there as a function which never gets called.
GCC requires main or WinMain as entry point. If neither of those entry points is found, then the compiler will complain. So let's just use main as entry point.
Py_Main presumably expects wide character string input. CommandLineToArgvW will always provide that. Example:
#include <Windows.h>
#include "include/Python.h"
int main()
{
int argc;
wchar_t** argv = CommandLineToArgvW( GetCommandLineW(), &argc );
return Py_Main(argc, argv);
}
If you still get the same error, just provide WinMain entry point to make it happy
#include <Windows.h>
#include "include/Python.h"
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
int argc;
wchar_t** argv = CommandLineToArgvW( GetCommandLineW(), &argc );
return Py_Main(argc, argv);
}
Also note, *.lib files are usually for Visual Studio. GCC version expects library names with *.a extension.

Exposing C++ to Python error from BoostPython

I'm exposing a simple C++ code to Python through BoostPython library:
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python.hpp>
using namespace boost::python;
bool test_api( void ){
return true;
};
BOOST_PYTHON_MODULE(materials) {
def( "test_api", test_api );
}
After I try to import this module, the python interpreter returns the error:
ImportError: ./example.so: undefined symbol: _Py_RefTotal
I've linked the module statically against the boost python library and the python dynamic libraries libpython3.2m.so and libpython3.2m.so.1.0 are present in the work directory.
Any suggestions on where to find the missing symbol?
The Boost libraries were not consistent with the Python installation.
cd boost_source
./bootstrap.sh --with-libraries=python --prefix=../boost_target
To configure Boost to point to the correct Python installation:
vim tools/build/v2/user-config.jam
Edit the line that points to the Python:
using python : version_number
: path_to_python_executable
: path_to_python_include_directory
: path_to_python_library_directory
Then, run the build system:
./b2
_Py_RefTotal is defined in object.h under a precompiler guard:
$less include/python3.6m/object.h
#ifdef Py_REF_DEBUG
PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
...
...
#endif /* Py_REF_DEBUG */
I was linking python3.6m but including headers from include/python3.6dm. Fixed issue including ptyhon3.6m

Building windows executable using pyqt with python embedded

I'm trying to make a windows application that runs some python code, more or less like what py2exe does but made by hand.
My application should run on windows without any external python dependencies (even the interpreter).
I've tested this (main.cpp):
#include <Python.h>
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("print \"Test\"\n");
Py_Finalize();
return 0;
}
When a build this I get a .exe file which upon execution prints Test on the console.
So far so good, but now I'm trying to build a minimal PyQt application as well, for that I put on the same folder of my .exe application the files
QtGui.pyd, QtGui4.dll, QtCore.pyd and QtCore4.dll, this is main.cpp:
#include <Python.h>
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("import QtGui as gui\n"
"\n"
"app = gui.QApplication([])\n"
"mw = gui.QMainWindow()\n"
"mw.show()\n"
"print \"Test\"\n"
"app.exec_()");
Py_Finalize();
return 0;
}
The problem is that when I run the built .exe file I got this error:
Traceback (most recent call last):
File "<string>", line 1, in <module>
SystemError: dynamic module not initialized properly
So I don't know what kind of initialization I need to do in order to use the .pyd files.
Finally these are my questions:
What I'm doing wrong?
If I need some kind of extra initialization, how could I do that and why it is needed? Maybe it's something inherent to the Qt bindings?
Should I copy another *pyd file to the working dir of the app?
Is this approach of using directly the .pyd files feasible? Or there is a better way to make an application like the one I want?
Note: I do not want to use any tool like py2exe, cx_Freeze, pyinstaller, etc. I want to build the app myself.

Categories

Resources