美文网首页
pybridge编译

pybridge编译

作者: HAPPYers | 来源:发表于2019-08-10 22:24 被阅读0次

    通过JNI实现和python的运行交互

    项目地址

    编译运行

    下载crystax ndk

    https://www.crystax.net/
    为了在Linux平台编译,此处下载的是crystax-ndk-10.3.2-linux-x86_64.tar.xz,如果要在Windows平台上编译,则下载crystax-ndk-10.3.2-windows-x86.exe即可。

    生成so文件

    切换到main/jni目录下面。

    1. 首先要修改一下Application.mk文件,选取自己需要的平台APP_ABI
    APP_PLATFORM := android-19
    APP_ABI := armeabi arm64-v8a x86 x86_64 armeabi-v7a  mips mips64
    

    生成各平台so文件的时候如果报类似app/src/main/obj/local/armeabi-v7a/objs/pybridge/pybridge.o.d:1: *** target pattern contains no %'. Stop.的错误,将src/main文件夹下的obj文件夹删除,再次生成即可。

    1. jni目录下运行path/to/crystax/ndk-build
      最后生成结果:文件都生成在src/main/libs的各平台文件夹下面,取所需要的平台即可。
     happy@ubuntu  ~/Source/pybridge/app/src/main/jni  /home/happy/Source/crystax-ndk-10.3.2/ndk-build
    [armeabi] Compile thumb  : pybridge <= pybridge.c
    [armeabi] SharedLibrary  : libpybridge.so
    [armeabi] Install        : libcrystax.so => libs/armeabi/libcrystax.so
    [armeabi] Install        : libpybridge.so => libs/armeabi/libpybridge.so
    [armeabi] Install        : libpython3.5m.so => libs/armeabi/libpython3.5m.so
    [arm64-v8a] Compile        : pybridge <= pybridge.c
    [arm64-v8a] SharedLibrary  : libpybridge.so
    [arm64-v8a] Install        : libcrystax.so => libs/arm64-v8a/libcrystax.so
    ......
    [mips64] SharedLibrary  : libpybridge.so
    [mips64] Prebuilt       : libgnustl_shared.so <= <NDK>/sources/cxx-stl/gnu-libstdc++/5/libs/mips64/
    [mips64] Install        : libcrystax.so => libs/mips64/libcrystax.so
    [mips64] Install        : libpybridge.so => libs/mips64/libpybridge.so
    [mips64] Install        : libpython3.5m.so => libs/mips64/libpython3.5m.so
    

    运行

    在Android studio中构建项目运行即可。


    魔改

    代码功能

    • AssetExtractor.java将APK的assets文件夹下的python文件拷贝到内部存储。很好的工具类,代码见此AssetExtractor
    • PyBridge.java控制与python解释器的交互
    • pybridge.c实现JNI C接口并处理CPython API
    • bootstrap.py Python解释器初始化时运行的脚本
      assets文件夹下的

    call python函数的实现

    /**
        This function is responsible for receiving a payload string
        and sending it to the router function defined in the bootstrap.py
        file.
    
    */
    JNIEXPORT jstring JNICALL Java_com_jventura_pybridge_PyBridge_call
            (JNIEnv *env, jclass jc, jstring payload)
    {
        LOG("Call into Python interpreter");
    
        // Get the payload string
        jboolean iscopy;
        const char *payload_utf = (*env)->GetStringUTFChars(env, payload, &iscopy);
    
        // Import module
        PyObject* myModuleString = PyUnicode_FromString((char*)"bootstrap");
        PyObject* myModule = PyImport_Import(myModuleString);
    
        // Get reference to the router function
        PyObject* myFunction = PyObject_GetAttrString(myModule, (char*)"router");
        PyObject* args = PyTuple_Pack(1, PyUnicode_FromString(payload_utf));
    
        // Call function and get the resulting string
        PyObject* myResult = PyObject_CallObject(myFunction, args);
        char *myResultChar = PyUnicode_AsUTF8(myResult);
    
        // Store the result on a java.lang.String object
        jstring result = (*env)->NewStringUTF(env, myResultChar);
    
        // Cleanup
        (*env)->ReleaseStringUTFChars(env, payload, payload_utf);
        Py_DECREF(myModuleString);
        Py_DECREF(myModule);
        Py_DECREF(myFunction);
        Py_DECREF(args);
        Py_DECREF(myResult);
    
        return result;
    }
    
    

    参考

    相关文章

      网友评论

          本文标题:pybridge编译

          本文链接:https://www.haomeiwen.com/subject/xsudjctx.html