Boost python shared library issue in specific case - python

I am trying to extend my c++ library which is created using qtcreator to python with boost::python. I create a setup.py like following:
from distutils.core import setup
from distutils.extension import Extension
module1 = Extension('FOO',
include_dirs = ['/usr/include/python3.4', '/home/user/cppProjects/FOOLib','/usr/include', '/usr/local/lib/python3.4/dit-packages'],
libraries = ['python3.4', 'boost_python-py34', 'boost_thread', 'boost_system', 'FOOLib'],
library_dirs = ['/usr/lib/x86_64-linux-gnu/', '/usr/lib/python3.4/config-3.4m-x86_64-linux-gnu/','/home/skywalker/cppProjects/build-FOO-Desktop-Debug/'],
sources = ['pythonprovider.cpp'],
extra_compile_args=['-std=c++11'])
setup(name="PackageName",
ext_modules=[module1])
and Bar.h
class Bar
{
public:
Bar(boost::python::list args)
{
...
}
static void SetN(int n)
{
Bar::N = n;
}
static int N;
};
and Bar.cpp
int Bar::N;
pythonprovider.cpp is
BOOST_PYTHON_MODULE(FOO)
{
class_<Bar>("Bar", init<list>());
}
Compiling the library and using in c++ app is working fine.
I am typing the following code in terminal and installation of python module is working fine.
sudo python3 setup.py install
Including the package in python like
from FOO import *
working fine. But when i modify the pythonprovider.cpp with static method
BOOST_PYTHON_MODULE(FOO)
{
class_<Bar>("Bar", init<list>())
.def("SetN", &Bar::SetN)
.staticmethod("SetN");
}
compiling and installation working fine but importing the module assert an error
ImportError: libFOO.so.1: cannot open shared object file: No such file or directory
This happen to me before. When i move to body of constructor from cpp file to header file problem is solved but in this case it is not solve my problem.

Related

how to use python with JNI or C++ in android project

I want to use python in my android application. But I do not want to use any framework like django or flask. So to achieve this functionality I decided to use c++ as a bridge between my android application and python. Because I have already used python with c++ in my past projects. Now I was trying the same method to use python in a c++ file which is a part of my android application but it is not working this time. When I try to build my app it throws an error.
The Error Is:-
config.py:- "io.h" file not found
Now let me describe what technique I am using to connect with python:-
I am using pybind11 to make a connection between my c++ and python module for that I have created a named
"methodchannel.cpp" inside app->src->main->cpp directory
In this cpp directory I have:-
One CMakeLlists.txt file
One cpp file named="methodchannel.cpp"
A directory named = "modules"
A directory named = "externals"
In this "externals" directory at number 4 I have my resurces of python and pybind11 and In my "modules" directory I have my python module or python script which will be used in my android project.
Here is my CPP or JNI code:-
#include "jni.h"
#include "iostream"
#include "externals\python\include/Python.h"
#include "externals\pybind11\include\pybind11\embed.h"
namespace py = pybind11;
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_methodchannel_MainActivity_00024Companion_getNum(JNIEnv *env, jobject thiz, jint num)
{
// TODO: implement getNum()
py::scoped_interpreter guard{};
auto module = py::module::import("modules.module");
auto func = module.attr("myfunc");
int result = func(num).cast<int>();
return 12 + result;
}

How to use pytthon with java native interface and c++ in android studio

I want to use python in my android application. But I do not want to use any framework like django or flask. So to achieve this functionality I decided to use c++ as a bridge between my android application and python. Because I have already used python with c++ in my past projects. Now I was trying the same method to use python in a c++ file which is a part of my android application but it is not working this time. When I try to build my app it throws an error.
The Error Is:-
config.py:- "io.h" file not found
Now let me describe what technique I am using to connect with python:-
I am using pybind11 to make a connection between my c++ and python module for that I have created a named
"methodchannel.cpp" inside app->src->main->cpp directory
In this cpp directory I have:-
One CMakeLlists.txt file
One cpp file named="methodchannel.cpp"
A directory named = "modules"
A directory named = "externals"
In this "externals" directory at number 4 I have my resurces of python and pybind11 and In my "modules" directory I have my python module or python script which will be used in my android project.
Here is my CPP or JNI code:-
#include "jni.h"
#include "iostream"
#include "externals\python\include/Python.h"
#include "externals\pybind11\include\pybind11\embed.h"
namespace py = pybind11;
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_methodchannel_MainActivity_00024Companion_getNum(JNIEnv *env, jobject thiz, jint num)
{
// TODO: implement getNum()
py::scoped_interpreter guard{};
auto module = py::module::import("modules.module");
auto func = module.attr("myfunc");
int result = func(num).cast<int>();
return 12 + result;
}
Here is an Image of my file system

error: [WinError 2] The system cannot find the file specified while using distutils in python

I am trying to call a C function from Python (Extending Python with C).
I built a hello.c file and a setup.py file. When I run the setup file it's supposed to build a Python extension so that I can import it in Python.
But, when I try to run python setup.py install I am getting the error
error: [WinError 2] The system cannot find the file specified
I tried setting up the environmental variable, insert path in to sys, but still the error persists.
Can someone identify where I'm going wrong?
setup.py:
from distutils.core import setup, Extension
module1 = Extension('helloworld', sources = ['hello.c'])
setup(name='helloworld', version='1.0', ext_modules=[module1])
hello.c:
#include <Python.h>
static PyObject* helloworld(PyObject* self, PyObject* args) {
return Py_BuildValue("s", "Hello, Python extensions!!");
}
static char helloworld_docs[] =
"helloworld( ): Any message you want to put here!!\n";
static PyMethodDef helloworld_funcs[] = {
{"helloworld", (PyCFunction)helloworld,
METH_NOARGS, helloworld_docs},
{NULL}
};
void inithelloworld(void) {
Py_InitModule3("helloworld", helloworld_funcs,
"Extension module example!");
}
error:

Python C Extension using numpy and gdal giving undefined symbol at runtime

I'm writing a C++ extension for python to speed up a raster image viewer created in-house.
I've got working code, but noticed that the speed hadn't increased that much and after profiling a bit deeper realised that it was due to the gdal.ReadAsArray calls, which were python callbacks from the C extension.
To get around the overhead of Python C-API when calling python objects I decided I would use the C++ libraries for gdal rather than using the Python callback to the existing gdalDataset. (space isn't a problem).
However after implementing the code for this I ran into an error at runtime(the extension compiled fine)
which was
import getRasterImage_new
ImportError: /local1/data/scratch/lib/python2.7/site-packages
/getRasterImage_new.so: undefined symbol: _ZN11GDALDataset14GetRasterYSizeEv
The code below replicates the error(some edits may be needed to run on your machines(ignore the uninitialised variables, it's just whats needed to replicate the error).
Python:
#!/usr/bin/env python
import numpy
from osgeo import gdal
import PythonCTest
print("test starting")
PythonCTest.testFunction(1)
print("test complete")
C++:
#include "Python.h"
#include "numpy/arrayobject.h"
#include "gdal_priv.h"
#include <iostream>
extern "C"{
static PyObject* PythonCTest_testFunction(PyObject* args);
static PyMethodDef PythonCTest_newMethods[] = {
{"testFunction", (PyCFunction)PythonCTest_testFunction, METH_VARARGS,
"test function"},
{NULL,NULL,0,NULL}};
PyMODINIT_FUNC initPythonCTest(void){
(void)Py_InitModule("PythonCTest",PythonCTest_newMethods);
import_array();
}
}
GDALDataset* y;
static PyObject* PythonCTest_testFunction(PyObject* args){
std::cout << "in testFunction\n";
y->GetRasterYSize();
std::cout << "doing stuff" << "\n";
return Py_None;
}
Any suggestions would be very welcome.
EDIT
You can also remove the from osgeo import gdal and the error stull occurs(only just noticed that).
EDIT 2
I forgot to say that I'm compiling my extension using distutils
current setup.py is
#!/usr/bin/env python
from distutils.core import setup, Extension
import os
os.environ["CC"] = "g++"
setup(name='PythonCTest', version='1.0', \
ext_modules=[Extension('PythonCTest', ['PythonCTest.cpp'],
extra_compile_args=['--std=c++14','-l/usr/include/gdal', '-I/usr/include/gdal'])])
A Python extension module is a dynamically loadable (shared) library. When linking a shared library, you need to specify its library dependencies, such as -lgdal and, for that matter, -lpython2.7. Failing to do so results in a library with unresolved symbols, and if those symbols are not provided by the time it is loaded, the loading will fail, as reported by Python.
To resolve the error, you need to add libraries=['gdal'] to Extension constructor. Specifying -lgdal in extra_compile_args won't work because compile arguments, as the name implies, are used for compilation and not for linking.
Note that an unresolved symbol would not go undetected when linking an executable, where the build would fail with a linker error. To get the same diagnostics when linking shared libraries, include -Wl,-zdefs in link arguments.

Importing python boost module

I built a DLL in VS2010 with boost::python to export some function to a python module:
myDLL.cpp:
std::string greet() { return "hello, world"; }
int square(int number) { return number * number; }
BOOST_PYTHON_MODULE(getting_started1)
{
// Add regular functions to the module.
def("greet", greet);
def("square", square);
}
Up to here, everything compiles just fine. I then get the myDLL.dll and myDLL.lib file in c:\myDLL\Debug.
According to boost doc (http://wiki.python.org/moin/boost.python/SimpleExample), I need to add this to PYTHONPATH, so I added c:\myDLL\Debug to it:
PYTHONPATH:
C:\Python27;c:\myDLL\Debug;
then, from my .py file, I try to import it:
import getting_started1
print getting_started1.greet()
number = 11
print number, '*', number, '=', getting_started1.square(number)
I have also tried from myDLL import getting_started1, and from getting_started1 import *, and all possible combinations of sorts.
Can anyone tell me how am I supposed to call my module? Thanks
EDIT:
According to cgohlke, there should be a getting_started1.pyd somewhere in my PYTHONPATH when I compile in VS? This file is inexistant... Do I have to set somethign different in VS2010? I have a default win32 DLL project.
But the boost doc says " If we build this shared library and put it on our PYTHONPATH", isn't a shared library on windows a DLL? ergo, the DLL should be in the PYTHONPATH?
The standard, portable way to build Python extensions is via distutils. However, Visual Studio 2010 is not a supported compiler for Python 2.7. The following setup.py works for me with Visual Studio 2008 and boost_1_48_0. The build command is python setup.py build_ext --inplace.
# setup.py
from distutils.core import setup
from distutils.extension import Extension
setup(name="getting_started1",
ext_modules=[
Extension("getting_started1", ["getting_started1.cpp"],
include_dirs=['boost_1_48_0'],
libraries = ['boost_python-vc90-mt-1_48'],
extra_compile_args=['/EHsc', '/FD', '/DBOOST_ALL_DYN_LINK=1']
)
])
For your Visual Studio 2010 project, try to change the linker output file to getting_started1.pyd instead of myDLL.dll.
I managed to get it working only in Release configuration and not in Debug.
From the project properties, on the General tab, modify Target Extension to .pyd
The project should be indeed a dll, as you did
In the Python script you need to specify the location of the dll as in this example:
import sys
sys.path.append("d:\\TheProjectl\\bin\\Release")
import getting_started #Dll name without the extension

Categories