• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Golang开发动态库的实现

    我们平时使用的动态库都是由C/C++开发最后生成的.so文件。

    可以先看看一个JNI的开发过程。

    一. 开发JNI

    有两种方式,现在一种比较快的方式是AndroidStudio你在创建项目选择Module的时候它会给你个JNI的模板,直接使用那个就行。

    但是我还是比较喜欢传统的方法。

    简单来说传统的方式就是你用命令来把java文件变成C++的头文件

    简单演示一遍,先写个java类

    public class TestJni {
    
      static {
        System.loadLibrary("KylimTest");
      }
    
      public static native String getMsg();
    
    }

    定义了一个native修饰的方法,在代码调用这个方法之后JNI就会自动调用到动态库中相应的方法。

    将这个类用命令生成头文件,来到文件夹路径下输入命令

    javah -jni 包名.类名

    可以看到默认会生成一个.h的头文件,自动命名为 包名_类名.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include jni.h>
    /* Header for class com_kylim_nativetest_TestJni */
    
    #ifndef _Included_com_kylim_nativetest_TestJni
    #define _Included_com_kylim_nativetest_TestJni
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:   com_kylim_nativetest_TestJni
     * Method:  getMsg
     * Signature: (I)Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_kylim_nativetest_TestJni_getMsg
     (JNIEnv *, jclass);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    主要的核心就是这句

    JNIEXPORT jstring JNICALL Java_com_kylim_nativetest_TestJni_getMsg
     (JNIEnv *, jclass);

    其它的我也不清楚,都是C相关的, 如果你嫌用命令生成麻烦,你可以自己创建一个.h文件然后方法命名就按照这样的规范去写

    头文件只是为了定义,我们需要自己写原文件,所以要创建一个.cpp结尾的文件

    #include "com_kylim_nativetest_TestJni.h"
    
    JNIEXPORT jstring JNICALL Java_com_kylim_nativetest_TestJni_getMsg
        (JNIEnv *env, jclass cls){
    
      jstring result = env->NewStringUTF("结果是");
      return result;
    }

    方法命名是有规范的,看Demo也知道怎么规范了,没必要多解释,这样两端的代码就写完了,但是仅仅这样是无法运行项目的。

    还需要些一些配置,因为在AndroidStudio中是Gradle去帮我们编译C++的代码,所以需要写这些配置。如果你不是用AS开发,你用其它工具开发直接生成.so文件再丢进AS中的话,可以忽略这一步。

    先看看我的Jni目录

    要创建一个Android.mk

    #固定写法
    LOCAL_PATH:=$(call my-dir)
    #固定写法
    include $(CLEAR_VARS)
    #生成so名称
    LOCAL_MODULE := KylimTest
    LOCAL_SRC_FILES := testone.cpp
    #固定写法
    include $(BUILD_SHARED_LIBRARY)

    具体的配置可自行去查找,这里不是主要讲JNI的,所以就不讲这么细。

    还需要一个Application.mk

    # 选择不同的 ABI,多个使用空格作为分隔符,全部是all
    # APP_ABI := armeabi armeabi-v7a
    APP_ABI := armeabi-v7a
    
    # 指定要使用的运行时
    APP_STL := c++_static

    当然这样还不行,都说了是Gradle进行编译,那么肯定还要在Gradle中写一些配置

    android {
       defaultConfig {
            ndkBuild {
            //指定 Application.mk 的路径
            arguments "NDK_APPLICATION_MK:=src/main/jni/Application.mk"
            //指定生成哪些平台的 so 文件
            abiFilters "armeabi-v7a"
            //cFlags 和 cppFlags 是用来设置环境变量的, 一般不需要动
            cFlags "-DTEST_C_FLAG1", "-DTEST_C_FLAG2"
            cppFlags "-DTEST_CPP_FLAG2", "-DTEST_CPP_FLAG2"
          }
       }
    
      sourceSets { main { jni.srcDirs = ['src/main/jni'] } }
    
      externalNativeBuild {
        ndkBuild {
          path file('src/main/jni/Android.mk')
        }
      }
    
    }

    这样就能简单的跑一个JNI的Demo,总的来说就是Java这边写一个类定义一些native方法和加载,C++这边写具体的方法实现。

    二.用Go开发动态库

    上面说的原生方法是用C/C++进行开发的,那么如果你不会C++的话怎么办,C++的学习也并非这么容易,就拿两边的类型来说,一开始新手肯定会碰到类型转换的问题,往往会先劝退一些人,但是Go不一样,有Java基础的话学起go还是挺快的。

    那么用Go开发的动态库是怎样的?也是SO文件吗,是不是也像C++一样,编译后经过某步操作生成SO文件。

    我看到网上有些文章确实是写怎么生成so的,但是说得太少,感觉不可靠,直到我看到官方有写。

    可以在官方中看到是有一个mobile的库的

    https://github.com/golang/mobile

    读下去它会指引你去wiki

    https://github.com/golang/go/wiki/Mobile

    可以看出它会打出一个aar的文件,那么aar对于我们接入来说确实很方法,但我很想探究这个aar里面究竟是什么,所以我们需要打出一个aar然后解压看看它里面到底是什么

    这里先说一下,下载这个库之前,你本地肯定先要配置好Go的环境

    然后按照这里的流程就行下载

    go get -d golang.org/x/mobile/example/basic

    但这输入这条命令需要科学上网的方式才能下载,总的来说很麻烦。

    所以我们可以直接克隆mobile的库,就是上面的这个链接 https://github.com/golang/mobile

    直接下载下来,除此之外,还需要tools,这些都在Go中,链接 https://github.com/golang/tools

    将这两个下载下来,然后拷贝到你的Go的以下路径

    go/src 创建一个文件夹golang.org/x ,把这两个文件夹丢进去

    然后输入命令

    gomobile init

    可以输入命令 查看安装配置是否成功

    gomobile bind -help

    如果配置成功会给你一些提示

    我感觉文档写得还是不算清楚,但是它有告诉你用什么命令生成aar

    gomobile bind -o app/hello.aar -target=android golang.org/x/mobile/example/bind/hello
    

    你在GoPath中创建一个Go文件,我是用GoLand进行开发的,项目的目录设置成GoPath,编写完之后,可以直接在文件中运行

    gomobile bind -o 输入文件名.aar -target=android

    这样就能在文件夹中生成一个aar

    接着我们看看aar里面是什么,解压

    首先可以看到生成这些ABI的so文件,再看看Manifest

    这里有限制最低版本,所以如果你的版本比他还低的话就需要注意一下了

    然后res里面是可以看到没有文件的。

    最后我们反编译class文件

    因为这不是Demo,直接是写公司的项目,所以有些地方要码,但是不影响。

    从这里看得出,go帮我们生成了一个java文件,这个java文件定义了再Go中命名的原生方法。

    其实从这里就可以看出,Go用的也基本是我们最上面写的JNI的方法,只是他帮你封装起来了而已

    但是他的原生代码是不是转成C++的我就不清楚了,因为我不会反编译SO文件。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    您可能感兴趣的文章:
    • golang实践-第三方包为私有库的配置方案
    • 完美解决golang go get私有仓库的问题
    • golang gopm get -g -v 无法获取第三方库的解决方案
    • Golang: 内建容器的用法
    • 浅谈golang 中time.After释放的问题
    • golang 定时任务方面time.Sleep和time.Tick的优劣对比分析
    • golang日志包logger的用法详解
    • Golang如何调用windows下的dll动态库中的函数
    上一篇:golang 网络框架之gin的使用方法
    下一篇:如何利用Golang解析读取Mysql备份文件
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Golang开发动态库的实现 Golang,开发,动态,库,的,实现,