加载静态库到android,静态库的提供方式有2种,

a. 通过源文件来编译静态库

b. 加载已经编译好的静态库

首先我们来看,通过源文件来编译静态库,工程目录如下

第一步:我们来看我们的jni目录,目录下包含以下4个文件

Android.mk  --- 编译文件

first.c ,first.h --- 外部需要引用的文件

second.c  ---- 我们的jni转换文件

首先我们简单的看下源码

#include "first.h"

int first(int  x, int  y)
{
return x + y;
}
first.c里面简单的定义了一个加法的方法,然后申明了头文件
 
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

second.c : 把first.c的方法转换为jni可以识别的方法。

#include "first.h"
#include <jni.h> jint
Java_com_example_twolibs_TwoLibs_add( JNIEnv* env,
jobject this,
jint x,
jint y )
{
return first(x, y);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

第二步是重点,我们来分析下mk文件,看编译文件是怎样生成first.c对于的静态文件,并在编译second.c的时候加载静态文件

   1:  LOCAL_PATH:= $(call my-dir)
   2:   
   3:  # first lib, which will be built statically
   4:  #
   5:  include $(CLEAR_VARS)
   6:   
   7:  LOCAL_MODULE    := libtwolib-first
   8:  LOCAL_SRC_FILES := first.c
   9:   
  10:  include $(BUILD_STATIC_LIBRARY)
  11:   
  12:  # second lib, which will depend on and include the first one
  13:  #
  14:  include $(CLEAR_VARS)
  15:   
  16:  LOCAL_MODULE    := libtwolib-second
  17:  LOCAL_SRC_FILES := second.c
  18:   
  19:  LOCAL_STATIC_LIBRARIES := libtwolib-first
  20:   
  21:  include $(BUILD_SHARED_LIBRARY)

如上: 1-10 行是生成静态文件的方法,

14-21 行是编译动态文件的方法,通过标识符BUILD_SHARED_LIBRARY 以及 BUILD_STATIC_LIBRARY 来区分是编译成动态文件还是静态,19行标识需要链接静态库libtwolib-first

第三步:在java中调用
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

public class TwoLibs extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState); TextView tv = new TextView(this);
int x = 1000;
int y = 42; // here, we dynamically load the library at runtime
// before calling the native method.
//
System.loadLibrary("twolib-second"); int z = add(x, y); tv.setText( "The sum of " + x + " and " + y + " is " + z );
setContentView(tv);
} public native int add(int x, int y);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

第二种方法: 用第3方提供的静态库来编译,我们还是用前面的jni文件

首先第一步我们通过gcc来生成静态库文件

gcc -c first.c   生成.o文件

ar -cr libtwolib-first.a first.o  来生成libtwolib-first.a库文件

然后通过 查看,方法多了一个”_”,这个坑爹了,还不知道怎么处理,网上没找到方法,这种方法只能先放放了。

那既然第一种不行,那是不是可以直接用原来的.mk文件来生成了,尝试了下,修改了mk文件,注释掉生成动态库的一部分。

LOCAL_PATH:= $(call my-dir)

# first lib, which will be built statically
#
include $(CLEAR_VARS) LOCAL_MODULE := libtwolib-first
LOCAL_SRC_FILES := first.c include $(BUILD_STATIC_LIBRARY) # second lib, which will depend on and include the first one
#
#include $(CLEAR_VARS) #LOCAL_MODULE := libtwolib-second
#LOCAL_SRC_FILES := second.c #LOCAL_STATIC_LIBRARIES := libtwolib-first #include $(BUILD_SHARED_LIBRARY)

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
       然后执行 ndk-build 什么反应都没有,经过查找一位大拿解决了,需要修改配置文件

NDK r6 默认不支持静态库的 install 操作。可以将 definitions.mk 脚本里的

D:\cygwin\home\Administrator\android-ndk-r8b\build\core\definitions.mk  1669行

module-class-is-installable = $(if $(NDK_MODULE_CLASS.$1.INSTALLABLE),$(true),$(false))

修改为:

module-class-is-installable = $(if $(NDK_MODULE_CLASS.$1.INSTALLABLE),$(true),$(true))

这样强制 NDK 对静态库进行 install,即可单独生成静态库
修改完以后,执行ndk-build,果然在/libs/armeabi目录下找到了库文件libtwolib-first.a
 方法也正常。
 
然后把.a文件拷贝到jni目录下,修改mk文件,去掉生成静态库部分,编译报错,找不到方法
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

经过查找才知道 “编译器改成windows版的了,/cygdrive/开头的cygwin下的路径不再支持,使用windows路径就可以了”

所以重新修改mk文件为如下

/usr/lib/gcc/i686-pc-cygwin/4.5.3/cc1.exe: error while loading shared libraries:
cygppl_c-2.dll: cannot open shared object file: No such file or directory

不用着急,这是因为在安装时,没有安装mpfr(版本4)所至,打开cygwin.exe,输入mpfr,下载libmpfr4至可

NDK 链接第三方静态库的方法

将NDK编译的第三方静态拷贝到JNI目录下,在Android.mk中添加如下代码

以openssl静态库(libcrypto-static.a)为例

第一种链接方法:LOCAL_LDFLAGS := libcrypto-static.a

第二种链接方法:LOCAL_LDLIBS := libcrypto-static.a

第三种链接方法:

include $(CLEAR_VARS)

LOCAL_MODULE := third_static_lib (可以随便起一个名字)

LOCAL_SRC_FILES := libcrypto-static.a

include $(PREBUILT_STATIC_LIBRARY)

//在你要编译的模块中引用third_static_lib

LOCAL_STATIC_LIBRARIES := third_static_lib

解决 NDK 编译静态库时没反应

(2012-12-11 14:22:02)

转载

标签:

杂谈

分类: Android

项目编译成动态库是正常的,将 Android.mk 里面的

include $(BUILD_SHARED_LIBRARY)

改成

include $(BUILD_STATIC_LIBRARY)

编译静态库,

运行 ndk-build 却一点反应都没有,一闪而过。


解决方案:

在 工程目录\jni\ 目录下添加一个 Application.mk 文件,里面只写上如下一行代码:

APP_MODULES := lib库名

问题解决。


目录结构示意图:

工程目录

|-jni

|  |-*.c/*.h <--多个源文件

|  |-Android.mk

|  |-Application.mk

|

|-Application.mk

1.工程目录/jni/Android.mk 文件内容:

# 提供当前文件的路径,必须定义它在你的 Android.mk 文件的开始处

LOCAL_PATH := $(call my-dir)


# CLEAR_VARS 变量是由生成系统已提供的,

# 并且指出一个特殊的 GNU Makefile 文件为你清除除了 LOCAL_PATH 以外的许多的 LOCAL_* 变量,

# 这是必须的,因为全部的生成控制文件是在一个单独的 GNU Make 执行环境中被分析的,

# 在那里所有的变量是全局的。

include $(CLEAR_VARS)


# 该变量是必须定义的,用来标识你的 Android.mk 文件中描述的每个模块,

# 模块名字必须是唯一的,并且不能包含任何的空格。

LOCAL_MODULE:= 模块名字


# 该变量是必须包含将要生成且汇编成一个模块所需的 C / C++ 源文件的列表。

# 注意:不列出头文件和包含文件在这里,因为生成系统将自动地为你估算信赖。

LOCAL_SRC_FILES := 多个源代码文件(*.c)用空格分隔


# 一个可选的路径列表,做为 include 搜索路径之一。

LOCAL_C_INCLUDES := $(LOCAL_PATH)


#include $(BUILD_SHARED_LIBRARY)

include $(BUILD_STATIC_LIBRARY)


2.工程目录/jni/Application.mk 文件内容:

# 该变量是可选的,指出你的应用程序工程名

APP_MODULES   := lib模块名字


3.工程目录/Application.mk 文件内容:

# 该文件是可选的,用来描述你的工程的更多细节,如:支持更多 CPU 以及替代编译器或链接器标志。

# 指出你的应用程序工程目录

APP_PROJECT_PATH := $(call my-dir)


# 默认情况下,NDK 生成系统将寻找一个名为 Android.mk 文件在 $(APP_PROJECT_PATH)/jni 目录下

APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/jni/Android.mk


注:工程目录/jni/Application.mk 文件内容,

  在编译动态库时,可以合并到 工程目录/Application.mk 文件内容 中。

NDK jni 加载静态库的更多相关文章

  1. android通过Jni加载so库遇到UnsatisfiedLinkError问题!!!

    错误信息: java.lang.UnsatisfiedLinkError: hsl.p2pipcam.nativecaller.NativeCaller at hsl.p2pipcam.manager ...

  2. -force_load (加载静态库崩溃)

    -force_load   Crash Log: Last Exception Backtrace: 0   CoreFoundation                 0x2f087f06 __e ...

  3. 【转载】cocos2dx 中 Android NDK 加载动态库的问题

     原文地址:http://blog.csdn.net/sozell/article/details/10551309 cocos2dx 中 Android NDK 加载动态库的问题 闲聊 最近在接入各 ...

  4. android java层通过jni加载使用第三方的so库

    1.例如我们自己编译一个so库,我们的其他模块要加载如何操作了 首先在c盘新建立一个文件夹sb,在sb下面新建立一个文件夹jni,如果你要使用ndk编译so库,必须需要有jni目录 2.在jni目录下 ...

  5. android开发 NDK 编译和使用静态库、动态库 (转)

    在eclipse工程目录下建立一个jni的文件夹 在jni文件夹中建立Android.mk和Application.mk文件 Android.mk文件: Android提供的一种makefile文件, ...

  6. Linux下c函数dlopen实现加载动态库so文件代码举例

    dlopen()是一个强大的库函数.该函数将打开一个新库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了. ...

  7. PostgreSql扩展Sql-动态加载共享库(C函数)

    基于 psql (PostgreSQL) 10.4 pg_language表定义了函数实现所使用的语言.主要支持了C语言和SQL语句.一些可选的语言包括pl/pgsql.tcl和perl. ligan ...

  8. Xilinx SDSoc 加载opencv库

    Xilinx SDSoc 加载opencv库需要下载两个文件 xfopencv 和 Revision Platform, Revision Platform需要和具体的开发板型号对应,我用的是zcu1 ...

  9. [转] c++加载外部库文件探究

    首先介绍:用#import导入dll和用#pragma comment导入lib还有在程序中LoadLibrary加载dll有什么区别 (1) #import导入的dll是com组建的dll,主要用来 ...

随机推荐

  1. ls 显示目录和文件的技巧

    摘自 http://hi.baidu.com/zaoyuan1217/blog/item/fd69575660366b4fd10906b9.html 要列出当前目录下所有的文件名和目录名直接使用ls命 ...

  2. jquery ajax请求了两次问题

    页面有一个请求form: <form method="post" id="signin"> <label for="orderid& ...

  3. PHP7安装问题解决

    ext/standard/info.o: In function `php_info_print_request_uri’: /root/php-5.4.16/ext/standard/info.c: ...

  4. C# 之 HttpWebResponse类

    提供 WebResponse 类的 HTTP 特定的实现.       继承层次结构 ,"System.Object→System.MarshalByRefObject→System.Net ...

  5. solr查询在solrconfig.xml中的配置

    <requestHandler name="/select" class="solr.SearchHandler"> <lst name=&q ...

  6. cocos2dx3.0-tinyxml在Android环境下解析xml失败的问题

    本文由@呆代待殆原创,转载请注明出处. 正常情况下,我们在用tinyxml读取xml文件的的时候,会像下面这样写. std::string filePath = FileUtils::getInsta ...

  7. ios-为银行卡号格式化 每隔四位添加一个空格

    -(NSString *)formatterBankCardNum:(NSString *)string { NSString *tempStr=string; NSInteger size =(te ...

  8. 7. Android框架和工具之 android-percent-support-lib-sample(百分比支持)

    1. android-percent-support-lib-sample介绍: 谷歌最新的百分比布局库的示例项目.其实LinearLayout的layout_weight也能实现百分比效果,不过这个 ...

  9. Oracle基础 TO_CHAR函数参考(转)

    Postgres 格式化函数提供一套有效的工具用于把各种数据类型(日期/时间,int,float,numeric)转换成格式化的字符串以及反过来从格式化的字符串转换成原始的数据类型. 注意:所有格式化 ...

  10. Java跳出循环-break和continue语句

    在实际编程中,有时需要在条件语句匹配的时候跳出循环.在Java里,由break和continue语句控制. “break”语句 “break”语句用来结束循环,即不再执行后边的所有循环. 示例:计算1 ...