首先是写一个.java文件,本例中是HprofDumper.java
具体如下:
public class HprofDumper {
public native boolean hprofDumper(String filename, String outname)
}
然后用命令javac HprofDumper.java 生成.class文件
再用javah HprofDumper 生成相应的.h文件
生成的.h文件如下
#include
#ifndef _Included_HprofDumper
#define _Included_HprofDumper
#ifdef __cplusplus
extern "C"世搜 {
#endif
JNIEXPORT jboolean JNICALL Java_HprofDumper_hprofDumper
(JNIEnv *, jobject, jstring, jstring)
#ifdef __cplusplus
}
#endif
#endif
然后只需要在对应的.cpp文件完成相应函数即可,核心代码如下:
#include "HprofDumper.h"
#include "hprof.h"
JNIEXPORT jboolean JNICALL Java_HprofDumper_hprofDumper
(JNIEnv *env, jobject obj, jstring in_file, jstring out_file)
{
const char *filename = env->GetStringUTFChars(in_file, 0)
const char *outname = env->GetStringUTFChars(out_file, 0)
return hprof_dump(filename, outname)
}
其中hprof_dump是纯c++代码,引入即可。
有一点需要注意,标红了已经,就是生成的.h文件函数并没具体形参名字,只有形参类型,在.cpp文件中要加橡模入相应的形参名字,本例为env、 obj、 in_file和out_file。
还有一点c和c++的区别,就是env的使用。
本例中C++为env->GetStringUTFChars(in_file, 0)
如果是C就应该改为(env)->GetStringUTFChars(env,in_file, 0)
调用Java类型 : C中调用Java中的String类型为 jstring
C语言方法名规则 : Java_完整包名类名_方法名(JNIEnv *env, jobject thiz), 注意完整的类名包名中包名的点要用 _ 代替
参数介绍 : C语言方法中有两个重要的搜如历参数, JNIEnv *env, jobject thiz
-- JNIEnv参数 : 该参数代表Java环境, 通过这个环境可以调用Java中的方法
-- jobject参数 : 该参数代表调用jni方法的类,
调用jni.h中的NewStringUTF方法 : 该方法的作用是在C语言中创建一个Java语言中的String类型对象, jni.h中是这样定义的 jstring (*NewStringUTF)(JNIEnv*, const char*), JNIEnv 结构体中包含了 NewStringUTF 函数指针, 通过 JNIEnv 就可以调用这个方法
完成代码编写后,在当前目录下完成Android.mk和Application.mk的编写
首先是Android.mk
本例中为:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hprof-dumper
LOCAL_C_INCLUDES += external/stlport/stlport
LOCAL_C_INCLUDES += bionic
LOCAL_C_INCLUDES += bionic/libstdc++/include
LOCAL_SRC_FILES := HprofDumper.cpp \
xx.cpp \
xx.cpp \
xx.cpp \
xx.cpp \
xx.cpp \
xx.cpp \
xxx.cpp
LOCAL_SHARED_LIBRARIES := libstlport
include $(BUILD_SHARED_LIBRARY)
注意标红的是最关键的,LOCAL_C_INCLUDES 顾名思义是需要的头文件的所在的目录,那三个参数主要为了引入STL,最重要!!LOCAL_SHARED_LIBRARIES 我一直生成失败就是没加这个参数,不光要引入头文件,还要引入具体的lib,这就是这个字段的作用。
具体字段的作用:
-- LOCAL_PATH : 代表mk文件所在的目录
-- include $(CLEAR_VARS) : 编译工具函数, 通过该函数可以进行一些初始化 *** 作
-- LOCAL_MODULE : 编译后的 .so 后缀文件叫什么名字
-- LOCAL_SRC_FILES: 指定编译的源文件名称
-- include $(BUILD_SHARED_LIBRARY) : 告诉编译器需要生成动态库
Applicaion.mk中就一行
APP_STL = stlport_static
表示使用stl静态库。
注意:我用了STL,大家没有用STL的当然不用引入这些啦~
1. 定义相关的目录(请修改为自己的相关目录) $ export NDKROOT=/opt/android/android-ndk-r10 $ export SYSROOT=$NDKROOT/platforms/android-19/arch-arm $ export GCC=$NDKROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc 2. 编译代码 $ $GCC -o main.out main.c --sysroot=$SYSROOT 3. 执行程序 $ adb push main.out /data/local/ $ adb shell $ /data/local/main.out 其核心思想其实很简单, 就是使用NDK提供的arm-linux-androideabi-gcc代替Linux下的gcc工具, 使用NDK提供的C头文件/库文件目录代替 Linux 下默认的目录, 其实, 使用gcc编译的时候默认的 sysroot设置为了本机的"/"目录, 等价于如下命令如蠢 : $ gcc -o main.out main.c --sysroot=/ 关备橡喊于如何在命令行下使用Android NDK交叉编译工具就介绍到这里了,希望对大仿野家有所帮助欢迎分享,转载请注明来源:内存溢出
评论列表(0条)