前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android 平台的Python——基础篇(一)

Android 平台的Python——基础篇(一)

作者头像
全栈程序员站长
发布2022-08-26 21:43:07
6K0
发布2022-08-26 21:43:07
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

Android 平台的Python——基础篇(一) Android 平台的Python——JNI方案(二) Android 平台的Python——CLE方案实现(三) Android 平台的Python——第三方库移植 Android 平台的Python——编译Python解释器 新篇——Android与Python混合编程

前言 (本文以Python3为例,Python3是未来,大家都懂的) Python作为一个功能强大又语法简洁的语言,其应用已无需多言。要想在Android平台运行起Python,也有方案实现,其实质就是在Android系统上搭建Python环境。对此Google已经提供了SL4A(Scripting Layer for Android )方案,支持多种脚本语言,除此之外,还可以使用一个叫QPython的app,可以直接在Android上编写以及运行Python代码。但其实意义不大,写好的Python代码并不是以一个独立的app进程运行的,只不过是在QPython这个应用中运行而已。这两者都不符合我现在要讨论的东西,如题,笔者想要讨论的是如何在Android平台使用Java与Python代码相互调用,换言之,就是如何在Android工程中嵌入一个Python解释器。

首先谈一点,为什么要在Android平台使用Python?Python拥有众多强大的第三方库和框架,在机器学习、大数据处理等诸多方面都有不俗的应用。另外,就语法而言,Python比Java更加简洁,同时又功能强大,既可面向过程亦可面向对象,而不像Java一样,是一种纯粹的面向对象语言,哪怕打印一句话也需要先创建类。Python作为一种脚本语言,可以边解释边执行,而不需编译,另外Python中存在的元类,可以使我们动态的创建类,如此可以在不需要重新编译安装apk的情况下,动态的由远程服务端为Android项目添加功能。我们还可以将Python已有的一些东西移植到Android平台,例如tornado、django等,总之玩法多多。

在Android平台,官方并不支持直接使用Python开发app,基于虚拟机的Java(或kotlin)才是更好的选择,其他语言是无法自如的使用官方Framework提供的api的,尤其是在程序界面的表现上,典型的反例就是kivy。什么是kivy,可自行了解,但要解决Android平台上Java与Python的交互,kivy确实是一个方向,而且是一个醍醐灌顶的方向。kivy实际上已经解决我们需要实现的目的,模仿Android平台上的kivy实现机制即可。但是,kivy使用了大量的Cython技术,而非CPython API接口,需要学习Cython语法,并且在其他一些方面存在一些限制。kivy给我们提供的思路就是借助Java的jni机制,实现Python与Java的交互。即在一个安卓apk工程中包含一个cython.so解释器,通过jni机制调用解释器去解释执行Python代码,通过Java调C,C调Python实现交互。有一点需要说明,Python作为一门胶水语言,Python与C的交互是非常方便的,因此才能实现这一系列调用。

关于该种方案,已有国外网友实践,原理如下

这里写图片描述
这里写图片描述

链接地址

除此之外,本博客将通过另外两种方案实现。其中第一种类似上述方案,但集成CPython解释器,非Cython,因此需要掌握如何实现Python与C的交互。

Python与C交互基础

C调用Python
  • 简单使用 流程:
    • 初始化Python解析器
    • 执行Python代码,字符串,对象或模块。
    • 关闭Python解析器。

    创建一个.c源文件,代码如下,创建一个pytest.py文件,实现一个printTime函数

代码语言:javascript
复制
	#include<Python.h>
	int main()
	{ 
   
	    Py_Initialize();//初始化Python解析器
	    if (!Py_IsInitialized())
	    { 
   
		    printf("Initialize failed");
		      return -1;
	    }
	    PyRun_SimpleString("print('hello C !')");
	    PyRun_SimpleString("import pytest");
	    PyRun_SimpleString("pytest.printTime()");
	    Py_Finalize();/关闭Python解析器
	    return 0;
	}		

注意:除了用PyRun_SimpleString函数直接运行代码,还可以使用PyRun_SimpleFile函数运行一个Python脚本 原型:PyRun_SimpleFile(FILE *fp, const char *filename) ,由于版本差异,使用该方式可能会造成崩溃,推荐另一种替代方式 PyRun_SimpleString(“execfile(“test.py”)”)

基础API

C API 调用

Python 对应

PyImport_ImportModel

import module

PyImport_ReloadModule

reload(module)

PyImport_GetModuleDict

module._dict_

PyDict_GetItemString

dict[key]

PyDict_SetItemString

dict[key] = value

PyDict_New

dict = {}

PyObject_GetAttrString

getattr(obj, attr)

PyObject_SetAttrString

setattr(obj, attr, val)

PyObject_CallObject

funcobj(*argstuple)

PyEval_CallObject

funcobj(*argstuple)

PyRun_String

eval(exprstr) , exec(stmtstr)

PyRun_File

exec(open(filename().read())

更多的接口调用以及数据类型转化,参照Python文档

这里写图片描述
这里写图片描述
Python 调用C

Python调用C有两种方式

  • 使用ctypes模块,Python文档有详细示例
这里写图片描述
这里写图片描述
  • 使用C为Python编写拓展模块 Python之所以如此强大,正是由于可以使用C\C++为其编写拓展模块,手动编写拓展模块的方式稍微有些繁琐,可借用SWIG自动实现,简洁快速。更多详细的SWIG用法,见其官方文档 官网下载 windows包并解压 使用vs创建空项目,并配置vs。右键当前项目,选择属性
这里写图片描述
这里写图片描述

现在使用C为Python创建一个叫user的拓展模块,该模块包含一个showHello函数: 分别创建三个文件 user.i user.c user_wrap.c

在user.i中添加如下代码

代码语言:javascript
复制
	%module user
	
	%inline %{ 
   
	extern void showHello();
	%}

user.c中添加

代码语言:javascript
复制
	#include <stdio.h>
	void showHello()
	{ 
   
		printf("hello Python!\n");
	}

右键user.i 文件并选择属性

这里写图片描述
这里写图片描述

点击应用后如下图,完成配置

这里写图片描述
这里写图片描述

右键当前项目,选择属性,完成如下配置,确定

这里写图片描述
这里写图片描述

最后生成即可(选择工具栏 生成 –> 批生成)

创建测试代码调用C验证

代码语言:javascript
复制
import user
user.show()

在Linux下则无需如此麻烦的配置,可直接使用命令

代码语言:javascript
复制
On Unix the compilation of examples is done using the file Example/Makefile. This makefile performs a manual module compilation which is platform specific. Typically, the steps look like this (Linux):


% swig -python interface.i
% gcc -fpic -c interface_wrap.c -I/usr/local/include/python1.5
% gcc -shared interface_wrap.o $(OBJS) -o interfacemodule.so 
% python
Python 1.5.2 (#3, Oct 9 1999, 22:09:34) [GCC 2.95.1 19990816 (release)] on linux2
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> import interface
>>> interface.blah(...)

此处.i文件为SWIG的接口文件,其中%module后面定义模块名,用%inline定义方法列表

代码语言:javascript
复制
%inline %{ 
   
包含导出的函数
%}

有了Python与C的交互基础,则还需要Android中的NDK开发基础,关于Android平台的jni调用,本文不在此处详解,可看看我的JNI方面博客,而此处我们需要使用Crystax NDK开发工具链,非官方NDK工具链,需自行下载。下一篇正式涉及Python for Android。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/145058.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python与C交互基础
    • C调用Python
      • Python 调用C
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档