Python C Extension implementation on Kivy Android¶
This section will give an basic implementation of python C extension on kivy android using recipe for buildozer / p4a
Template for building the Android application
https://github.com/VICTORVICKIE/Kivy_Python_C_Extension_Demo
Kivy app¶
Create a project folder (Kivy_Python_C_Extension_Demo)
Kivy_Python_C_Extension_Demo
|
├── custom_lib
|
├── python-for-android
|
└── main.py
|
└── buildozer.spec
Create a basic kivy app (main.py)
from kivy.app import App
from kivy.uix.label import Label
from custom_lib import custom_module
class PyCExtensionApp(App):
def build(self):
return Label(text=custom_module.custom_hello())
if __name__ == '__main__':
PyCExtensionApp().run()
This app just displays the text of string from the C Extension for demonstration.
C Extension¶
In the project directory
create a folder for the library (custom_lib) this contains all the requirements for the C Extension
setup.py / setup.cfg
and src folder format package (custom_lib, This is different from previous one!)
In the src folder we need a __init__.py for package and a module file (Here C Extension)
And the structure should look similar to this
custom_lib
|
├── setup.cfg
|
├── setup.py
|
└── custom_lib
|
├── custom_module.c
|
└── __init__.py
In custom_module.c
#include <Python.h>
static PyObject* custom_hello(PyObject* self){
return PyUnicode_FromString("Hello from Custom Lib");
}
static struct PyModuleDef methods[] = {
{"custom_hello", (PyCFunction)custom_hello, METH_NOARGS},
{NULL, NULL}
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"custom_module",
NULL,
-1,
methods
};
PyMODINIT_FUNC PyInit_custom_module(void) {
return PyModule_Create(&module);
}
Setuptools¶
from setuptools import find_packages, Extension, setup
setup(
name = 'custom_lib',
version = '0.1',
description = 'This package contains some sample hello world C code',
author = 'VIGNESH KUMAR S',
author_email = 's.vickie14@gmail.com',
url = 'https://github.com/VICTORVICKIE/Kivy_Python_C_Extension_Demo',
packages = find_packages(),
ext_package = 'custom_lib',
ext_modules = [Extension('custom_module',['custom_lib/custom_module.c'])],
entry_points = {'console_scripts': ['custom-lib-cli = custom_lib.custom_module:custom_hello', ], },
)
Install the custom_lib by running the below command in directory where your setup.py exists
❯ pip install .
Output
The output of the above command should be something like this,
❯ Successfully built custom-lib
❯ Successfully installed custom-lib-0.1
Now check if the custom_lib works, with the cli command given in entry_points
❯ custom-lib-cli
Output
The output of the above command depends on your entry_points!
here,
❯ Hello from Custom Lib
One final step to integrate the extension module with the application.
Recipe¶
https://python-for-android.readthedocs.io/en/latest/recipes/
Recipes are special scripts for compiling and installing different programs (including Python modules) into a p4a distribution. They are necessary to take care of compilation for any compiled components, as these must be compiled for Android with the correct architecture.
python-for-android
|
└── recipe
|
└── custom_lib
|
└── __init__.py
from pythonforandroid.recipe import CompiledComponentsPythonRecipe
class BillBookLibRecipe(CompiledComponentsPythonRecipe):
site_packages_name = 'custom_lib'
depends = ['setuptools']
call_hostpython_via_targetpython = False
def should_build(self, arch):
return True
recipe = BillBookLibRecipe()
Buildozer¶
# In requirements make sure to mention the C Extension Module
requirements = python3,kivy,custom_lib
# Specify the path for the setup.py / setup.cfg for local C Extension Module
requirements.source.custom_lib = ./custom_lib/
# Specify the path for Recipe for local C Extension Module
p4a.local_recipes = ./python-for-android/recipe