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

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;
}

Related

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

pybind with third-party C++ on Windows (ImportError: DLL load failed)

I'm trying to use a third-party c++ lib from python using pybind11.
I have managed to do it using pure C++ code, but, when I add the third-party code I get the following error:
ImportError: DLL load failed while importing recfusionbind
Here's my code:
#include <RecFusion.h>
#include <pybind11/pybind11.h>
using namespace RecFusion;
bool isValidLicense() {
return RecFusionSDK::setLicenseFile("License.dat");
}
namespace py = pybind11;
PYBIND11_MODULE(recfusionbind, m) {
m.def("isValidLicense", &isValidLicense, R"pbdoc(
Check if there is a valid license file.
)pbdoc");
#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
}
If i change, for testing purposes, the return of the function to simply true it works just fine. But calling the third-party library gives the above mentioned error. I have put RecFusion.dll on the current directory (where the python script is), with same results.
Any tips on what I'm missing will be welcomed. Lib is 64 bits, same as my code.
This seems to me like a linking problem. Look at your dll's import table (with tools like PE explorer or IDA). Now validate that the function RecFusionSDK::setLicenseFile is indeed imported from a dll named RecFusion.dll and not some other dll name.
Also validate that the mangled function name in RecFusion.dll's export table and in your dll match. If not, this could be an ABI problem.

How do I import a dll-module written in C++ to Python using PyBind11

I've been having trouble getting pybind11 to work the way described here.
I was able to build the example DLL in Visual Studio 2019 but I don't understand how to actually get a Python script to recognize the module using an 'import' statement.
This the test module written in C++ (compiles without any issues):
#include <pybind11/pybind11.h>
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("add", &add, "A function which adds two numbers");
This is my test Python script which attempts to call the module:
import example
print(example.add(1,2))
The above simply fails to identify the module - i.e. "ModuleNotFoundError: No module named 'example'"
I've placed my Python script in the same folder as the DLL build (containing various files - .obj, .iobj,.lib etc. )
I'm running Python 3.8 on Windows 10 if it matters.
I've been bashing my head against Boost.Python all day before finally finding pybind11 but I can't get it to work!!

How do I setup a CMakeLists.txt file to get xtensor-python sample code up and running

I'm trying to use xtensor-python example found here.
I have xtensor-python, pybind11, and xtensor installed and also created a CMakeLists.txt.
from /build I ran.
$ cmake ..
$ make
and it builds without errors.
My CMakeLists.txt looks like this.
cmake_minimum_required(VERSION 3.15)
project(P3)
find_package(xtensor-python REQUIRED)
find_package(pybind11 REQUIRED)
find_package(xtensor REQUIRED)
My example.cpp file.
#include <numeric> // Standard library import for std::accumulate
#include "pybind11/pybind11.h" // Pybind11 import to define Python bindings
#include "xtensor/xmath.hpp" // xtensor import for the C++ universal functions
#define FORCE_IMPORT_ARRAY // numpy C api loading
#include "xtensor-python/pyarray.hpp" // Numpy bindings
double sum_of_sines(xt::pyarray<double>& m)
{
auto sines = xt::sin(m); // sines does not actually hold values.
return std::accumulate(sines.cbegin(), sines.cend(), 0.0);
}
PYBIND11_MODULE(ex3, m)
{
xt::import_numpy();
m.doc() = "Test module for xtensor python bindings";
m.def("sum_of_sines", sum_of_sines, "Sum the sines of the input values");
}
My python file.
import numpy as np
import example as ext
a = np.arange(15).reshape(3, 5)
s = ext.sum_of_sines(v)
s
But my python file can't import my example.cpp file.
File "examplepyth.py", line 2, in <module>
import example as ext
ImportError: No module named 'example'
I am new to cmake. I would like to know how to set this project up properly with CMakeLists.txt
The recommended way is to build and install with a setup.py file instead of cmake. You can use the cookie-cutter to get the boilerplate generated for you.
Hey I am not sure about xtensor-python since I have not used it, but I might give you some pointers for building pybind11 with cmake within an Anaconda environment. Your Cmake.txt looks a bit incomplete. For me the following set-up works:
In my Anaconda-shell I use the following commands:
cmake -S <folder where Cmake.txt is> B <folder where Cmake.txt is\build> -G"Visual Studio 15 2017 Win64"
which puts all the linking into the subfolder build, so the actual building can be done via
cmake --build build
The necessary Cmake.txt looks something like below. The created library TEST is then located in the subfolder debug\Build
#minimum version of cmake
cmake_minimum_required(VERSION 2.8.12)
#setup project
project(TEST)
#load the libraries
find_package(pybind11 REQUIRED)
set(EXTERNAL_LIBRARIES_ROOT_PATH <Filepath where my external libraries are at>)
set(EIGEN3_INCLUDE_DIR ${EXTERNAL_LIBRARIES_ROOT_PATH}/eigen-eigen-c753b80c5aa6)
#get all the files in the folder
file(GLOB SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/*.h
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)
#include the directories
include_directories(${PYTHON_INCLUDE_DIRS} ${pybind11_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIR})
pybind11_add_module(TEST MODULE ${SOURCES})
#in some cases need to link the libraries
#target_link_libraries(TEST PUBLIC ${OpenCV_LIBRARIES} ${Boost_LIBRARIES})
If you want a working minimal example for which I use exactly this Cmake.txt file, it happens to be in another question I posted here on stackoverflow: pybind11 how to use custom type caster for simple example class
Hope this helps as a first starting point (I left the EIGEN3 inside as to give you an idea how it is done with a header-only library. For actual libraries like OpenCV you need the target_link_libraries command in addition).

Boost python shared library issue in specific case

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.

Categories