脚手架搭设验收单:NDK动态库的调用 - zhangweia - 博客园

来源:百度文库 编辑:偶看新闻 时间:2024/05/05 15:39:24
zhangweia

NDK动态库的调用

  NDK动态库的调用分两种情况。第一种是:so库和调用程序在同一个目录和源程序 通过同一个mk文件来编译;另外一种情况是so是外部已经编译好了的,调用程序加载调用。下面我们就来分析下面2种so的调用情况:

第一部分: 内部so调用

      A. 先看下工程的目录:

               

          test01.java  :Java文件

          test01.c 主so,生成libtest.so,在libtest.so中调用libtutorial.so中的方法

          tutorial01.c tutorial02.c tutorial02.h :生成libtutorial.so

     B. 然后看下具体的mk文件的写法以及java中的文件内容

test01.java/** Copyright (C) 2009 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.example.test;import android.R.integer;import android.app.Activity;import android.widget.TextView;import android.os.Bundle;public class test01 extends Activity{/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);/* Create a TextView and set its content.* the text is retrieved by calling a native* function.*/TextView  tv = new TextView(this);int a = getinformation();String lls = a +"";tv.setText(lls);setContentView(tv);}/* A native method that is implemented by the* 'hello-jni' native library, which is packaged* with this application.*/public native int  getinformation();/* this is used to load the 'hello-jni' library on application* startup. The library has already been unpacked into* /data/data/com.example.HelloJni/lib/libhello-jni.so at* installation time by the package manager.*/static {System.loadLibrary("test");}}

Android.mk     LOCAL_PATH := $(call my-dir)#获取当前目录include $(CLEAR_VARS)#清除一些变量LOCAL_MODULE    := tutorial#要生成的库名LOCAL_SRC_FILES := tutorial01.c tutorial02.c#库对应的源文件include $(BUILD_SHARED_LIBRARY)#生成动态库libtutorial.soinclude $(CLEAR_VARS)#清除一些变量LOCAL_MODULE    := test#定义另外一个库的名LOCAL_SRC_FILES := test01.c#定义库对应的源文件LOCAL_LDLIBS := -ldl -llog#libtest.so需要引用的库libdl.so:加载动态函数需要,liblog.so 日志打印需要,默认是system/lib目录下include $(BUILD_SHARED_LIBRARY)#生成共享库

 

test01.c#include #include #include #include #include #define  LOG_TAG    "libgl2jni"#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)//extern int getinformation();jint Java_com_example_test_test01_getinformation(JNIEnv* env,jobject thiz){//getinformation();   ??thr .so file will load to the sdcard with the folder data/data/com.example.test/lib/void*  filehandle = dlopen("/data/data/com.example.test/lib/libtutorial.so", RTLD_LAZY );int ll = -1;if(filehandle){LOGI("open so success!");int( * getinformation ) ();getinformation = dlsym(filehandle, "getinformation");if( getinformation ){LOGI("call function getinformation OK!");ll = getinformation();}else{ll = -3;LOGE("call function getinformation! ERROR!");}LOGI("return value=%d",ll);dlclose(filehandle);filehandle=0;}else{ll = -2;LOGE("open so ERROR!");}return ll;}

tutorial01.c#include #include "tutorial02.h"int getinformation(){int c = getinformation2(191,81);return c;}

 

 

tutorial02.c#include #include "tutorial02.h"int getinformation2(int i,int j){return (i+j);}


 

tutorial02.hint getinformation2(int,int);

C: 编译:

    进入工程目录,执行  $NDK/ndk-build

    输出结果:

$NDK/ndk-build/cygdrive/e/cygwin/android-ndk-r4Compile thumb  : test <= /cygdrive/e/cygwin/android-ndk-r4/samples/testappso/jni/test01.cSharedLibrary  : libtest.soInstall        : libtest.so => /cygdrive/e/cygwin/android-ndk-r4/samples/testappso/libs/armeabiCompile thumb  : tutorial <= /cygdrive/e/cygwin/android-ndk-r4/samples/testappso/jni/tutorial01.cCompile thumb  : tutorial <= /cygdrive/e/cygwin/android-ndk-r4/samples/testappso/jni/tutorial02.cSharedLibrary  : libtutorial.soInstall        : libtutorial.so => /cygdrive/e/cygwin/android-ndk-r4/samples/testappso/libs/armeabi

D:在重新刷新工程,你就可以在lib下面看到生成的so了,点击加载运行

 

第二部分:调用通过自己编写make方式生成的so

      我们还是引用上面的工程,不过把libtutorial.so拿出来,通过自己写makefile来编译成so,这里请大家注意了,调用外部的so时候,不能够直接用在linux下生产的so来调用,必须通过ndk提供的gcc来编译,否则会因为平台的不同无法调用。

     A. 废话不多说,看makefile怎么写!我的ndk是1.6版本的.

         新建一个文件夹,把 tutorial01.c  tutorial02.c  tutorial02.h 文件拷贝过去,然后编写makefile文件

libtutorial.so MakefileCC = /cygdrive/e/cygwin/android-ndk-r4/build/prebuilt/windows/arm-eabi-4.4.0/bin/arm-eabi-gcc-4.4.0CFLAGS  = -g -O2 -fPIC -I/cygdrive/e/cygwin/android-ndk-r4/build/platforms/android-5/arch-arm/usr/includeSDFLAGS = -nostdlib -Wl,-T,armelf.xsc -Wl,-shared,-Bsymbolic -Wl,-soname,$@ -lcCRT_OBJS= -L/cygdrive/e/cygwin/android-ndk-r4/build/platforms/android-5/arch-arm/usr/lib -lz -lm  -ldl# source files:SRCS= tutorial01.c tutorial02.c tutorial02.hall: libtutorial.solibtutorial.so: tutorial01.o tutorial02.o$(CC) $(SDFLAGS) -o $@ tutorial01.o tutorial02.o  $(CRT_OBJS)tutorial01.o: tutorial02.htutorial02.o: tutorial02.hclean:rm -f libtutorial.so *.o

在执行make的时候需要注意一下几点:

1.  指定程序需要的头文件目录 通过-I指定/cygdrive/e/cygwin/android-ndk-r4/build/platforms/android-5/arch-arm/usr/include NDK提供的一些基本c语言库的头文件

2.  指定库路径-L/cygdrive/e/cygwin/android-ndk-r4/build/platforms/android-5/arch-arm/usr/lib 里面有libz.so,libm.so,libdl.so等库的路径

3.  拷贝交叉编译文件armelf.xsc到android-ndk-r4/build/prebuilt/windows/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0下,armelf.xsc在目录./build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/ldscripts下

4.  拷贝libc.so到./build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0目录下,libc.so位于./build/platforms/android-5/arch-arm/usr/lib库

完成上面的工作你就可以放心make了,成功后生成libtutorial.so文件


 

libtest.so MakefileCC = /cygdrive/e/cygwin/android-ndk-r4/build/prebuilt/windows/arm-eabi-4.4.0/bin/arm-eabi-gcc-4.4.0CFLAGS  = -g -O2 -fPIC -I/cygdrive/e/cygwin/android-ndk-r4/build/platforms/android-5/arch-arm/usr/includeSDFLAGS = -nostdlib -Wl,-T,armelf.xsc -Wl,-shared,-Bsymbolic -Wl,-soname,$@ -lcCRT_OBJS= -L/cygdrive/e/cygwin/android-ndk-r4/build/platforms/android-5/arch-arm/usr/lib -lz -lm  -ldl# source files:SRCS= test01.call: libtest.solibtest.so: test01.o$(CC) $(SDFLAGS) -o $@ test01.o  $(CRT_OBJS)test01.o: test01.cclean:rm -f libtest.so *.o

B. 生成so文件后,在工程目录下建立目录libs/armeabi,然后把so拷贝进去,在打开工程,刷新加载,一切搞定

C.  一些小技巧:

    a. 查看so是不是编译成ARM模式下的so

         $ file libtest.so
         libtest.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped

    b.  如果别人提供了你一个so,查看提供了那些方法,更详细的用法,查看nm命令

$ nm libtutorial.so |grep T
00001344 a _GLOBAL_OFFSET_TABLE_
000002a8 T getinformation
000002b4 T getinformation2

D.  下面提供一个大工程的编译的makefile,吧opencore --omx下的testapp独立编译成so,编译通过,未加载库,给大家参考。

testapp Makefilecc=/home/zhangweia/android/android-ndk-r4b/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-gcc-4.4.0CFLAGS = -g -O2 -fPIC -DANDROID -I./include -I/home/zhangweia/android/android-ndk-r4b/build/platforms/android-5/arch-arm/usr/includeCFLAGS += -I$(SDK)/out/target/product/generic/obj/include/libpv -I$(opencore)/codecs_v2/common/include -I$(opencore)/pvmi/pvmf/include -I$(opencore)/nodes/common/include -I$(opencore)/extern_libs_v2/khronos/openmax/include -I$(opencore)/build_config/opencore_dynamic -I$(opencore)/android/drm/oma1/src -I$(opencore)/engines/author/include -I$(opencore)/oscl/oscl/config/shared -I$(opencore)/oscl/oscl/config/android -I$(opencore)/engines/common/include -I$(opencore)/extern_libs_v2/khronos/openmax/include -I$(opencore)/android #SDFLAGS = -nostdlib -Wl,-T,armelf.xsc -Wl,-shared,-Bsymbolic -Wl,-soname,$@ -lcSDFLAGS = -nostdlib -Wl,-T,armelf.xsc -Wl,-Bsymbolic -Wl,-soname,$@ -lcCRT_OBJS=-L/home/zhangweia/android/android-ndk-r4b/build/platforms/android-5/arch-arm/usr/lib -lz -lm  -ldl#all : libomxde.soOBJECT= omx_threadsafe_callbacks.o omxdectest.o omxdectestbase.o omxtest_buffer_busy.o omxtest_corrupt_nal.o omxtest_dynamic_reconfig.o omxtest_eos_missing.o omxtest_extra_partialframes.o omxtest_flush_eos.o omxtest_flush_port.o omxtest_get_role.o omxtest_incomplete_nal.o omxtest_missing_nal.o omxtest_multiple_instance.o omxtest_param_negotiation.o omxtest_partialframes.o omxtest_pause_resume.o omxtest_portreconfig_transit_1.o omxtest_portreconfig_transit_2.o omxtest_portreconfig_transit_3.o omxtest_reposition.o omxtest_usebuffer.o omxtest_without_marker.o#libomxde.so : $(OBJECT)omxde : $(OBJECT)$(cc) $(SDFLAGS) -o $@ $(CRT_OBJS)omx_threadsafe_callbacks.o:src/omx_threadsafe_callbacks.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omx_threadsafe_callbacks.cppomxdectest.o:src/omxdectest.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxdectest.cppomxdectestbase.o:src/omxdectestbase.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxdectestbase.cppomxtest_corrupt_nal.o:src/omxtest_corrupt_nal.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_corrupt_nal.cppomxtest_buffer_busy.o:src/omxtest_buffer_busy.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_buffer_busy.cppomxtest_dynamic_reconfig.o:src/omxtest_dynamic_reconfig.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_dynamic_reconfig.cppomxtest_eos_missing.o:src/omxtest_eos_missing.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_eos_missing.cppomxtest_extra_partialframes.o:src/omxtest_extra_partialframes.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_extra_partialframes.cppomxtest_flush_eos.o:src/omxtest_flush_eos.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_flush_eos.cppomxtest_flush_port.o:src/omxtest_flush_port.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_flush_port.cppomxtest_get_role.o:src/omxtest_get_role.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_get_role.cppomxtest_incomplete_nal.o:src/omxtest_incomplete_nal.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_incomplete_nal.cppomxtest_missing_nal.o:src/omxtest_missing_nal.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_missing_nal.cppomxtest_multiple_instance.o:src/omxtest_multiple_instance.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_multiple_instance.cppomxtest_param_negotiation.o:src/omxtest_param_negotiation.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_param_negotiation.cppomxtest_partialframes.o:src/omxtest_partialframes.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_partialframes.cppomxtest_pause_resume.o:src/omxtest_pause_resume.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_pause_resume.cppomxtest_portreconfig_transit_1.o:src/omxtest_portreconfig_transit_1.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_portreconfig_transit_1.cppomxtest_portreconfig_transit_2.o:src/omxtest_portreconfig_transit_2.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_portreconfig_transit_1.cppomxtest_portreconfig_transit_3.o:src/omxtest_portreconfig_transit_3.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_portreconfig_transit_1.cppomxtest_reposition.o:src/omxtest_reposition.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_reposition.cppomxtest_usebuffer.o:src/omxtest_usebuffer.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_usebuffer.cppomxtest_without_marker.o:src/omxtest_without_marker.cpp$(cc) $(CFLAGS) $(SDFLAGS) -c src/omxtest_without_marker.cppclean:rm -rf *.o

     

 

 


 

 

 

 


分类: Android NDK标签: NDK Makefile so绿色通道:好文要顶关注我收藏该文与我联系