array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 在NDK开发中引入第三方库(AndroidStudio Cmake) - 爱码网


原文:http://blog.csdn.net/mxw3755/article/details/56676923
官方:https://developer.android.com/studio/projects/add-native-code.html#specify-abi
在NDK中可能需要复用之前已经编译好的so文件,所以本章的目标是给一个之前编译好的so文件外加一个需要调用接口的头文件,在现在项目中复用。

在本次实践过程中,已经有编译完成的各种cpu架构的libstringutil-lib.so以及头文件,Stringutil.h
头文件中简单定义了两个接口:
class StringUtil {
public:
static char* toLower(char* chars);
static char* toUpper(char* chars);
};
顾名思义上述接口已在libstringutil-lib.so中实现

现有工程需要调用这些接口,步骤如下:
1、在java层创建native接口
package dev.mars.jnidemo;

public class StringUtils {
    static {
        System.loadLibrary("native-lib");
    }
    public static native String toLower(String str);
    public static native String toUpper(String str);
}



2、由Android Studio自动生成native层接口定义,native-lib是实现接口的cpp文件:
extern "C" {
JNIEXPORT jstring JNICALL
Java_dev_mars_jnidemo_StringUtils_toLower(JNIEnv *env, jclass type, jstring str_) {
    const char *str =  env->GetStringUTFChars(str_, 0);
    char* str2 =new char[strlen(str)];
    strcpy(str2,str);
    StringUtil::toLower(str2);
    return env->NewStringUTF(str2);
}

JNIEXPORT jstring JNICALL
Java_dev_mars_jnidemo_StringUtils_toUpper(JNIEnv *env, jclass type, jstring str_) {
    const char *str =  env->GetStringUTFChars(str_, 0);
    char* str2 =new char[strlen(str)];
    strcpy(str2,str);
    StringUtil::toUpper(str2);
    return env->NewStringUTF(str2);
}
}


此时编译器应该找不到StringUtil的定义,因此需要将Stringutil.h拷贝到cpp文件所在的文件夹下,本工程中如图所示,新建一个include文件夹,将头文件拷贝过去:
然后在native-lib.cpp中加入头文件的引用:
在NDK开发中引入第三方库(AndroidStudio Cmake)
#include <string>
#include <android/log.h>
#include "include/StringUtil.h"


3、将所有so文件拷贝到工程的libs/jni目录下
在NDK开发中引入第三方库(AndroidStudio Cmake)
4、修改app下的gradle文件,在android{}中加入如下代码,将so文件作为引用
sourceSets {
    main {
        jniLibs.srcDirs = ['./libs/jni']
    }
}

5、下面是最为关键的CmakeLists.txt的配置

cmake_minimum_required(VERSION 3.4.1)

#定义变量ProjectRoot为工程根目录,用相对路径没通过编译,可能是路径写错,以后再试
#本次使用绝对路径作为参数
set(ProjectRoot G:/AndroidStudioProjects/JNIDemo)

#将native-lib加入到编译源中
add_library( native-lib SHARED src/main/jni/native-lib.cpp )

#动态方式加载 stringutil-lib是libxxxx.so的xxxx部分
add_library(stringutil-lib SHARED IMPORTED)

#设置要连接的so的相对路径,${ANDROID_ABI}表示so文件的ABI类型的路径,这一步引入了动态加入编译的so
set_target_properties(stringutil-lib  PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/jni/${ANDROID_ABI}/libstringutil-lib.so)

find_library( log-lib log )

#配置加载native依赖
#include_directories( ${ProjectRoot}/app/src/main/jni/include )

#这里多出了引用的stringutil-lib
target_link_libraries(
                       native-lib
                       stringutil-lib
                       ${log-lib} )

6、测试代码


总结
最为关键的两个步骤
1、在gradlle中指定本地的jni相对路径
2、在CmakeLists.txt中指定加入编译的so及其绝对路径

#动态方式加载 stringutil-lib是libxxxx.so的xxxx部分
add_library(stringutil-lib SHARED IMPORTED)

#设置要连接的so的相对路径,${ANDROID_ABI}表示so文件的ABI类型的路径,这一步引入了动态加入编译的so
set_target_properties(stringutil-lib PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/jni/${ANDROID_ABI}/libstringutil-lib.so)

#这里多出了引用的stringutil-lib
target_link_libraries(
native-lib
stringutil-lib
${log-lib} )

由于时间不多,未调试出在CmakeLists.txt 中使用相对路径的办法,我在编译中总是报找不到so的错误。有任何问题欢迎交流。

参考:
原文:http://blog.csdn.net/mxw3755/article/details/56676923
官方:https://developer.android.com/studio/projects/add-native-code.html#specify-abi
在NDK中可能需要复用之前已经编译好的so文件,所以本章的目标是给一个之前编译好的so文件外加一个需要调用接口的头文件,在现在项目中复用。

在本次实践过程中,已经有编译完成的各种cpu架构的libstringutil-lib.so以及头文件,Stringutil.h
头文件中简单定义了两个接口:
class StringUtil {
public:
static char* toLower(char* chars);
static char* toUpper(char* chars);
};
顾名思义上述接口已在libstringutil-lib.so中实现

现有工程需要调用这些接口,步骤如下:
1、在java层创建native接口
package dev.mars.jnidemo;

public class StringUtils {
    static {
        System.loadLibrary("native-lib");
    }
    public static native String toLower(String str);
    public static native String toUpper(String str);
}



2、由Android Studio自动生成native层接口定义,native-lib是实现接口的cpp文件:
extern "C" {
JNIEXPORT jstring JNICALL
Java_dev_mars_jnidemo_StringUtils_toLower(JNIEnv *env, jclass type, jstring str_) {
    const char *str =  env->GetStringUTFChars(str_, 0);
    char* str2 =new char[strlen(str)];
    strcpy(str2,str);
    StringUtil::toLower(str2);
    return env->NewStringUTF(str2);
}

JNIEXPORT jstring JNICALL
Java_dev_mars_jnidemo_StringUtils_toUpper(JNIEnv *env, jclass type, jstring str_) {
    const char *str =  env->GetStringUTFChars(str_, 0);
    char* str2 =new char[strlen(str)];
    strcpy(str2,str);
    StringUtil::toUpper(str2);
    return env->NewStringUTF(str2);
}
}


此时编译器应该找不到StringUtil的定义,因此需要将Stringutil.h拷贝到cpp文件所在的文件夹下,本工程中如图所示,新建一个include文件夹,将头文件拷贝过去:
然后在native-lib.cpp中加入头文件的引用:
在NDK开发中引入第三方库(AndroidStudio Cmake)
#include <string>
#include <android/log.h>
#include "include/StringUtil.h"


3、将所有so文件拷贝到工程的libs/jni目录下
在NDK开发中引入第三方库(AndroidStudio Cmake)
4、修改app下的gradle文件,在android{}中加入如下代码,将so文件作为引用
sourceSets {
    main {
        jniLibs.srcDirs = ['./libs/jni']
    }
}

5、下面是最为关键的CmakeLists.txt的配置

cmake_minimum_required(VERSION 3.4.1)

#定义变量ProjectRoot为工程根目录,用相对路径没通过编译,可能是路径写错,以后再试
#本次使用绝对路径作为参数
set(ProjectRoot G:/AndroidStudioProjects/JNIDemo)

#将native-lib加入到编译源中
add_library( native-lib SHARED src/main/jni/native-lib.cpp )

#动态方式加载 stringutil-lib是libxxxx.so的xxxx部分
add_library(stringutil-lib SHARED IMPORTED)

#设置要连接的so的相对路径,${ANDROID_ABI}表示so文件的ABI类型的路径,这一步引入了动态加入编译的so
set_target_properties(stringutil-lib  PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/jni/${ANDROID_ABI}/libstringutil-lib.so)

find_library( log-lib log )

#配置加载native依赖
#include_directories( ${ProjectRoot}/app/src/main/jni/include )

#这里多出了引用的stringutil-lib
target_link_libraries(
                       native-lib
                       stringutil-lib
                       ${log-lib} )

6、测试代码


总结
最为关键的两个步骤
1、在gradlle中指定本地的jni相对路径
2、在CmakeLists.txt中指定加入编译的so及其绝对路径

#动态方式加载 stringutil-lib是libxxxx.so的xxxx部分
add_library(stringutil-lib SHARED IMPORTED)

#设置要连接的so的相对路径,${ANDROID_ABI}表示so文件的ABI类型的路径,这一步引入了动态加入编译的so
set_target_properties(stringutil-lib PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/jni/${ANDROID_ABI}/libstringutil-lib.so)

#这里多出了引用的stringutil-lib
target_link_libraries(
native-lib
stringutil-lib
${log-lib} )

由于时间不多,未调试出在CmakeLists.txt 中使用相对路径的办法,我在编译中总是报找不到so的错误。有任何问题欢迎交流。

参考:

相关文章: