I am trying to reproduce the Boost.Python tutorial on how to do a wrap a C/C++ file for python.
This is the cpp file which builded successfuly.
#include "boost/python.hpp"
class SaySomething
{
public:
void set(std::string msg)
{
this->msg = msg;
}
std::string greet()
{
return msg;
}
std::string msg;
};
BOOST_PYTHON_MODULE(SaySomething)
{
namespace python = boost::python;
python::class_<SaySomething>("SaySomething")
.def("greet", &SaySomething::greet)
.def("set", &SaySomething::set)
;
}
In the same directory of the source code I have the python file
import SaySomething
msg = SaySomething.SaySomething()
msg.set('howdy')
msg.greet()
When I try to run the python file this error occurs
ModuleNotFoundError: No module named 'SaySomething'
I tried moving the compiled library to the same folder with no success. The tutorial doesn't elaborate on how to make the C++ file seen by the interpreter.
Edit
As some have suggested I have edited the extension of the compiled shared library to .pyd so python can see it. This creates a second error
ImportError: DLL load failed: The specified module could not be found.
This issue is exactly like mine. The solution suggests to add Boost.python to environnement variable. I know how to add path to this but I'm not sure what path I want, the boost.python dlls (or lib)? Just boost?
Related
I have this C code i took from https://docs.python.org/3/extending/embedding.html:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("import numpy as np \n"
"student = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')])\n"
"print(student)\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
It compiles and runs quite nicely in a machine that has python3 and python3-numpy installed.
The output:
[('name', 'S20'), ('age', 'i1'), ('marks', '<f4')]
However, if the target machine does not have numpy installed, the output is:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'numpy'
My question: is it possible to run the python code from the app executable in a target machine that has no Python3 nor numpy installed? If so, how do i do it?
I mostly thinking of Win10 as a target machine, but i guess my question would equally apply to other OSes.
Thanks!
EDIT: To be more exact, I am not asking if this code can be compiled without having Python installed. I know it must have some python-dev to be compiled.
But what I want to know is there a way to create an .exe file that uses some Python calls without having Python installed in the target machine?
Use PyInstaller. It will wrap your Python code, a Python interpreter, and the packages you need into a standalone .exe file.
Specifically, numpy is on the list of supported packages.
I would get rid of the C program, put your main Python code in a .py file, and let PyInstaller do the work for you.
This is a much better solution than requiring your users to have a Python interpreter installed, much less any particular libraries and packages. It allows each application to have its own version of Python and packages.
Full details are in the PyInstaller docs.
Is there a way to execute Python code before the site module is imported?
In case it matters, I'm asking because I'm running an embedded Python interpreter via Py_Initialize, and I'd like to configure the Python environment using Python code, however it's important this happens before the site module is imported since the changes impact how it initializes.
You can set Py_NoSiteFlag to suppress loading of site.py while initializing Python interpreter. site could be loaded later-on manually.
Here is a minimal example:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
Py_NoSiteFlag = 1; /* Suppress 'import site' */
Py_Initialize();
PyRun_SimpleString("import sys; print('site' in sys.modules)\n");
//There are no site-packages in path:
PyRun_SimpleString("print(sys.path)\n");
// do what must be done
// ....
//now, import site manually,
//call site.main(), so site-packages are added to sys.path:
PyRun_SimpleString("import site; site.main()");
//now, site-packages are in path:
PyRun_SimpleString("print(sys.path)\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
return 0;
}
When running the resulting executable, one sees that site isn't loaded in Py_Initialize (first printed line is False) and is loaded later. We also need to call site.main() explicitly for site-packages to be put into sys.path.
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
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.
I'm having a great deal of trouble using my c++ code from Visual C++ (wrapped by boost) in Python.
Alright, so the tools I'm using are: Visual Studio 2010, BoostPro 1_47, Windows 7, and Python 2.7 (32-bit).
I have the following code which compiles nicely in Visual Studio 2010:
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python.hpp>
using namespace boost::python;
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
BOOST_PYTHON_MODULE(hello)
{
class_<World>("World")
.def("greet", &World::greet)
.def("set", &World::set);
}
It's in the format: Win32 Console Application >>>Empty Project / DLL.
In "Project Properties":
VC++ DIRECTORIES:
I added:
>>> INCLUDE DIRECTORIES: C:\Program Files\boost\boost_1_47;C:\Python27\include .
>>> LIBRARY DIRECTORIES: C:\Program Files\boost\boost_1_47\lib;C:\Python27\libs
All of this makes the c++ file build but then I can't access it from Python.
This is what Python says when I try to use the module:
">>> import hello
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
import hello
ImportError: No module named hello
So I guess my question is... How can I get Python to find it???
When the c++ code compiles it creates a DLL file. Do I have to change the location of the file? If so, where should I put it?
Your help would be greatly appreciated
AFAIK you have to change the extension of the DLL to .pyd or otherwise Python will not be able to load it. I think you can set a build option to automatically set the extension in VS, but I don't know for sure.
Also, make sure that the created extension is somewhere on the PYTHONPATH, the path, python will look for modules to load.