日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

不懂这几个问题就落后了:Python、Android开发者必读!

發(fā)布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不懂这几个问题就落后了:Python、Android开发者必读! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Android 平臺的Python:

(本文以Python3為例,Python3是未來,大家都懂的)

Python作為一個功能強大又語法簡潔的語言,其應(yīng)用已無需多言。要想在Android平臺運行起Python,也有方案實現(xiàn),其實質(zhì)就是在Android系統(tǒng)上搭建Python環(huán)境。對此Google已經(jīng)提供了SL4A(Scripting Layer for Android )方案,支持多種腳本語言,除此之外,還可以使用一個叫QPython的app,可以直接在Android上編寫以及運行Python代碼。但其實意義不大,寫好的Python代碼并不是以一個獨立的app進(jìn)程運行的,只不過是在QPython這個應(yīng)用中運行而已。這兩者都不符合我現(xiàn)在要討論的東西,如題,筆者想要討論的是如何在Android平臺使用Java與Python代碼相互調(diào)用,換言之,就是如何在Android工程中嵌入一個Python解釋器。

首先談一點,為什么要在Android平臺使用Python?Python擁有眾多強大的第三方庫和框架,在機器學(xué)習(xí)、大數(shù)據(jù)處理等諸多方面都有不俗的應(yīng)用。另外,就語法而言,Python比Java更加簡潔,同時又功能強大,既可面向過程亦可面向?qū)ο?#xff0c;而不像Java一樣,是一種純粹的面向?qū)ο笳Z言,哪怕打印一句話也需要先創(chuàng)建類。Python作為一種腳本語言,可以邊解釋邊執(zhí)行,而不需編譯,另外Python中存在的元類,可以使我們動態(tài)的創(chuàng)建類,如此可以在不需要重新編譯安裝apk的情況下,動態(tài)的由遠(yuǎn)程服務(wù)端為Android項目添加功能。我們還可以將Python已有的一些東西移植到Android平臺,例如tornado、django等,總之玩法多多。

在Android平臺,官方并不支持直接使用Python開發(fā)app,基于虛擬機的Java(或kotlin)才是更好的選擇,其他語言是無法自如的使用官方Framework提供的api的,尤其是在程序界面的表現(xiàn)上,典型的反例就是kivy。什么是kivy,可自行了解,但要解決Android平臺上Java與Python的交互,kivy確實是一個方向,而且是一個醍醐灌頂?shù)姆较颉ivy實際上已經(jīng)解決我們需要實現(xiàn)的目的,模仿Android平臺上的kivy實現(xiàn)機制即可。但是,kivy使用的是Cython解釋器,非CPython解釋器,需要學(xué)習(xí)Cython語法,并且在其他一些方面存在一些限制。kivy給我們提供的思路就是借助Java的jni機制,實現(xiàn)Python與Java的交互。即在一個安卓apk工程中包含一個cython.so解釋器,通過jni機制調(diào)用解釋器去解釋執(zhí)行Python代碼,通過Java調(diào)C,C調(diào)Python實現(xiàn)交互。有一點需要說明,Python作為一門膠水語言,Python與C的交互是非常方便的,因此才能實現(xiàn)這一系列調(diào)用。

也為大家推薦了技術(shù)教程:

Android視頻編碼和直播推流

Android高手進(jìn)階

一天掌握Scrapy爬蟲框架

【Python全棧】網(wǎng)絡(luò)爬蟲體驗課

Django Web框架/Python最牛框架

探究Linux的總線、設(shè)備、驅(qū)動模型

Linux 實用講解+實操+面試題

zabbix企業(yè)實戰(zhàn)應(yīng)用

Linux視頻教程

關(guān)于該種方案,已有國外網(wǎng)友實踐,原理如下

?

鏈接地址

除此之外,本博客將通過另外兩種方案實現(xiàn)。其中第一種類似上述方案,但集成CPython解釋器,非Cython,因此需要掌握如何實現(xiàn)Python與C的交互。

Python與C交互基礎(chǔ)

C調(diào)用Python

  • 簡單使用
  • 流程:
  • 初始化Python解析器
  • 執(zhí)行Python代碼,字符串,對象或模塊。
  • 關(guān)閉Python解析器。
  • 創(chuàng)建一個.c源文件,代碼如下,創(chuàng)建一個pytest.py文件,實現(xiàn)一個printTime函數(shù)
#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();/關(guān)閉Python解析器
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

注意:除了用PyRun_SimpleString函數(shù)直接運行代碼,還可以使用PyRun_SimpleFile函數(shù)運行一個Python腳本

原型:PyRun_SimpleFile(FILE *fp, const char *filename) ,由于版本差異,使用該方式可能會造成崩潰,推薦另一種替代方式

PyRun_SimpleString(“execfile(“test.py”)”)

  • 調(diào)用Python函數(shù)
  • pytest.py
import time

def printTime():
print('invoke printTime:'+str(time.time()))
return (1,)#元組只有一個元素時,需在末尾加逗號
  • 1
  • 2
  • 3
  • 4
  • 5
  • C 代碼
int main()
{
PyObject * module_name,*module,*func,*dic;
char * fun_name = "printTime";//需調(diào)用的Python函數(shù)名
PyObject *resultValue;

Py_Initialize();
if (!Py_IsInitialized())
{
printf("Initialize failed");
return -1;
}

//導(dǎo)入Python 模塊并檢驗
module_name = Py_BuildValue("s", "pytest");
module = PyImport_Import(module_name);


if (!module)
{
printf("import test failed!");
return -1;
}

//獲取模塊中的函數(shù)列表,是一個函數(shù)名和函數(shù)地址對應(yīng)的字典結(jié)構(gòu)
dic = PyModule_GetDict(module);
if (!dic)
{
printf("failed ! ");
return -1;
}

func = PyDict_GetItemString(dic, fun_name);
if (!PyCallable_Check(func))
{
printf("not find %s ", fun_name);
return -1;
}

int r;
//獲取Python函數(shù)返回值,是一個元組對象
resultValue = PyObject_CallObject(func, NULL);
PyArg_ParseTuple(resultValue, "i", &r);
printf("result :%d ", r);

Py_DECREF(module);
Py_DECREF(dic);
Py_Finalize();
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 基礎(chǔ)api
  • C API 調(diào)用Python 對應(yīng)PyImport_ImportModelimport modulePyImport_ReloadModulereload(module)PyImport_GetModuleDictmodule.__dict__PyDict_GetItemStringdict[key]PyDict_SetItemStringdict[key] = valuePyDict_Newdict = {}PyObject_GetAttrStringgetattr(obj, attr)PyObject_SetAttrStringsetattr(obj, attr, val)PyObject_CallObjectfuncobj(*argstuple)PyEval_CallObjectfuncobj(*argstuple)PyRun_Stringeval(exprstr) , exec(stmtstr)PyRun_Fileexec(open(filename().read())
  • Py_BuildValue()函數(shù)
  • 作用:將C/C++類型類型的數(shù)據(jù)轉(zhuǎn)變成PyObject*對象。
  • 原型:PyAPI_FUNC(PyObject*) Py_BuildValue(const char *format, …);
  • 參數(shù)解釋:
  • format及轉(zhuǎn)換格式,類似與C語言中%d,%f,后面的不定參數(shù)對應(yīng)前面的格式,具體格式如下:
  • “s”(string) [char *] :將C字符串轉(zhuǎn)換成Python對象,如果C字符串為空,返回NONE。
  • “s#”(string) [char *, int] :將C字符串和它的長度轉(zhuǎn)換成Python對象,如果C字符串為空指針,長度忽略,返回NONE。
  • “z”(string or None) [char *] :作用同”s”。
  • “z#” (stringor None) [char *, int] :作用同”s#”。
  • “i”(integer) [int] :將一個C類型的int轉(zhuǎn)換成Python int對象。
  • “b”(integer) [char] :作用同”i”。
  • “h”(integer) [short int] :作用同”i”。
  • “l(fā)”(integer) [long int] :將C類型的long轉(zhuǎn)換成Pyhon中的int對象。
  • “c”(string of length 1) [char] :將C類型的char轉(zhuǎn)換成長度為1的Python字符串對象。
  • “d”(float) [double] :將C類型的double轉(zhuǎn)換成python中的浮點型對象。
  • “f”(float) [float] :作用同”d”。
  • “O&”(object) [converter, anything] :將任何數(shù)據(jù)類型通過轉(zhuǎn)換函數(shù)轉(zhuǎn)換成Python對象,這些數(shù)據(jù)作為轉(zhuǎn)換函數(shù)的參數(shù)被調(diào)用并且返回一個新的Python對象,如果發(fā)生錯誤返回NULL。
  • “(items)”(tuple) [matching-items] :將一系列的C值轉(zhuǎn)換成Python元組。
  • “[items]”(list) [matching-items] :將一系列的C值轉(zhuǎn)換成Python列表。
  • “{items}”(dictionary) [matching-items] :將一系類的C值轉(zhuǎn)換成Python的字典,每一對連續(xù)的C值將轉(zhuǎn)換成一個鍵值對。
  • 例:
  • 后面為PyObject的返回值
 Py_BuildValue("")None

Py_BuildValue("i",123) 123

Py_BuildValue("iii",123, 456, 789) (123, 456, 789)

Py_BuildValue("s","hello") 'hello'

Py_BuildValue("ss","hello", "world") ('hello', 'world')

Py_BuildValue("s#","hello", 4) 'hell'

Py_BuildValue("()")()

Py_BuildValue("(i)",123) (123,)

Py_BuildValue("(ii)",123, 456) (123, 456)

Py_BuildValue("(i,i)",123, 456) (123, 456)

Py_BuildValue("[i,i]",123, 456) [123, 456] Py_BuildValue("{s:i,s:i}", "abc",123, "def", 456) {'abc': 123, 'def': 456}

Py_BuildValue("((ii)(ii))(ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • PyArg_ParseTuple函數(shù)
  • 作用:此函數(shù)其實相當(dāng)于sscanf(str,format,…),是Py_BuildValue的逆過程,這個函數(shù)將PyObject參數(shù)轉(zhuǎn)換成C/C++數(shù)據(jù)類型,傳遞的是指針,但這個函數(shù)與Py_BuildValue有點不同,這個函數(shù)只能解析Tuple元組,而Py_BuildValue函數(shù)可以生成元組,列表,字典等。
  • 原型:PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *args, const char *format,…)
  • Args:一般為Python程序返回的元組。
  • Foramt:與Py_BulidValue類型,就不在累述咯。
  • 元組操作函數(shù):
  • 因為程序之間傳遞的參數(shù),大多數(shù)為Tuple類型,所以有專門的函數(shù)來操作元組:
  • PyAPI_FUNC(PyObject *)PyTuple_New(Py_ssize_t size);
  • 解釋:新建一個參數(shù)列表(調(diào)試了下,發(fā)現(xiàn)其實是用鏈表實現(xiàn)的),size列表為長度的寬度
  • PyAPI_FUNC(Py_ssize_t)PyTuple_Size(PyObject *);
  • 解釋:獲取該列表的大小
  • PyAPI_FUNC(PyObject )PyTuple_GetItem(PyObject , Py_ssize_t);
  • 解釋:獲取該列表某位置的值
  • PyAPI_FUNC(int) PyTuple_SetItem(PyObject ,Py_ssize_t, PyObject );
  • 解釋:設(shè)置該列表此位置的值。如PyTuple_SetItem(pyParams,1,Py_BuildValue(“i”,2));設(shè)置第2個位置的值為2的整數(shù)。
  • 備注:對應(yīng)的列表和字典也有對應(yīng)的操作

更多的接口調(diào)用以及數(shù)據(jù)類型轉(zhuǎn)化,參照Python文檔

?

Python 調(diào)用C

Python調(diào)用C有兩種方式

  • 使用ctypes模塊,Python文檔有詳細(xì)示例

?

  • 使用C為Python編寫拓展模塊
  • Python之所以如此強大,正是由于可以使用CC++為其編寫拓展模塊,手動編寫拓展模塊的方式稍微有些繁瑣,可借用SWIG自動實現(xiàn),簡潔快速。更多詳細(xì)的SWIG用法,見其官方文檔
  • 官網(wǎng)下載 windows包并解壓
  • 使用vs創(chuàng)建空項目,并配置vs。右鍵當(dāng)前項目,選擇屬性

?

  • 現(xiàn)在使用C為Python創(chuàng)建一個叫user的拓展模塊,該模塊包含一個showHello函數(shù):
  • 分別創(chuàng)建三個文件
  • user.i
  • user.c
  • user_wrap.c
  • 在user.i中添加如下代碼
%module user
%inline %{
extern void showHello();
%}
  • 1
  • 2
  • 3
  • 4
  • user.c中添加
 
#include <stdio.h>

void showHello()
{
printf("hello Python! ");

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 右鍵user.i 文件并選擇屬性

?

  • 點擊應(yīng)用后如下圖,完成配置

?

  • 右鍵當(dāng)前項目,選擇屬性,完成如下配置,確定

?

  • 最后生成即可(選擇工具欄 生成 –> 批生成)
  • 創(chuàng)建測試代碼調(diào)用C驗證
import user
user.show()
  • 1
  • 2
  • 在Linux下則無需如此麻煩的配置,可直接使用命令
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(...)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 此處.i文件為SWIG的接口文件,其中%module后面定義模塊名,用%inline定義方法列表
%inline %{
包含導(dǎo)出的函數(shù)
%}
  • 1
  • 2
  • 3

有了Python與C的交互基礎(chǔ),則還需要Android中的NDK開發(fā)基礎(chǔ),關(guān)于Android平臺的jni調(diào)用,本文不在此處詳解,可看看我的JNI方面博客,而此處我們需要使用Crystax NDK開發(fā)工具鏈,非官方NDK工具鏈,需自行下載。下一篇正式涉及Python for Android。

轉(zhuǎn)載于:https://www.cnblogs.com/ndsc2018/p/9584432.html

總結(jié)

以上是生活随笔為你收集整理的不懂这几个问题就落后了:Python、Android开发者必读!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。