要使用jni首先要配置NDK以及CDT,配置好之后,下面来简要说明一下使用jni的一些步骤:
(一)创建jni相应的C++文件
1>生成jni相应的头文件
我是这样做的,当我需要在java中调用一些函数的时候,我会把这写函数
单独写在一个.java文件中(当然如果你熟悉jni的一些数据类型的转换以及命名规则后就可以自己写,跳过第(一)步了),
比如如下所示:
这个例子中的源文件为: UsageJniActivity.java
- public class UsageJniActivity {
- public native float resultofmultiply(int n1, int n2);
- public native float calculateGapOfTwoPoint(int nx1, int ny1, int nx2,
- int ny2);
- public native void setString(String strText);
- }
在终端上先cd到该文件所在的目录
1)编译这个源文件
javac UsageJniActivity.java
生成UsageJniActivity.class
2)生成相应的头文件
javah UsageJniActivity
生成的UsageJniActivity.h文件内容如下:
- /* DO NOT EDIT THIS FILE - it is machine generated */
- #include <jni.h>
- /* Header for class UsageJniActivity */
- #ifndef _Included_UsageJniActivity
- #define _Included_UsageJniActivity
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * Class: UsageJniActivity
- * Method: resultofmultiply
- * Signature: (II)F
- */
- JNIEXPORT jfloat JNICALL Java_UsageJniActivity_resultofmultiply
- (JNIEnv *, jobject, jint, jint);
- /*
- * Class: UsageJniActivity
- * Method: calculateGapOfTwoPoint
- * Signature: (IIII)F
- */
- JNIEXPORT jfloat JNICALL Java_UsageJniActivity_calculateGapOfTwoPoint
- (JNIEnv *, jobject, jint, jint, jint, jint);
- /*
- * Class: UsageJniActivity
- * Method: setString
- * Signature: (Ljava/lang/String;)V
- */
- JNIEXPORT jstring JNICALL Java_UsageJniActivity_getString
- (JNIEnv *, jobject);
- #ifdef __cplusplus
- }
- #endif
- #endif
将头文件重命名为Calculate.h
2>创建Calculate.cpp文件并实现相关的函数,如下:
- #include "Calculate.h"
- JNIEXPORT jfloat JNICALL Java_UsageJniActivity_resultofmultiply(
- JNIEnv * env, jobject thiz, jint a, jint b) {
- return a * b;
- }
- JNIEXPORT jfloat JNICALL JNICALL Java_UsageJniActivity_calculateGapOfTwoPoint(
- JNIEnv * env, jobject thiz, jint nx1, jint ny1, jint nx2, jint ny2) {
- float fvalue = (nx1 - nx2) * (nx1 - nx2) + (ny1 - ny2) * (ny1 - ny2);
- return fvalue;
- }
- JNIEXPORT jstring JNICALL Java_UsageJniActivity_getString(
- JNIEnv * env, jobject thiz) {
- char str[] = { "hello everyone" };
- return env->NewStringUTF(str);
- }
这样关于jni的c++部分代码已经写完了。
(ps:这里需要说明一下,函数的名称不是随意的,在这里为Java_UsageJniActivity_resultofmultiply,
其中Java_是都一样的,UsageJniActivity_为包以及类名,下面如果要使用的话还需将函数的名字进行修改,
使之与包名及类名相一致,否则会报错)。
(二)android中使用jni
1>首先创建一个android工程,假设为UsageJni, 包的结构为com.usejni,在工程的目录下创建一个文件夹,名字
为jni,将Calculate.h以及Calculate.cpp文件拷贝进去,将函数名进行相应的修改(前面说过),将Java_UsageJniActivity_ 改为Java_com_usejni_UsageJniActivity_同时还要创建两个文件Android.mk以及Application.mk,内容分别如下:
Android.mk:
- # 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.
- #
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := Calculate
- LOCAL_SRC_FILES := Calculate.cpp
- LOCAL_LDLIBS := -llog
- include $(BUILD_SHARED_LIBRARY)
Application.mk:
- APP_ABI := armeabi x86
- APP_STL := stlport_static
2>代码算是写完了,接下来就是一些琐碎的配置过程。
(1)为了能在eclipse中对jni文件进行编译调试,要将工程转化一下,具体步骤如下:
File->New->Other->C/C++->Convert to a c/c++ project
在project type:中选择Makefile project
在Toolchains:中选择--Other Toolchain然后点击Finish。
(2)添加NDK编译命令,在工程上点击右键,选择属性,弹出属性对话框,
选择C/C++ Build在Build Settings中去掉use default build command
在build command中输入 ndk-build点击ok结束。
(3)现在已经可以对整个工程进行编译,运行了。
(4)完成第三步后想必大家也会发现一个问题,就是工程虽然可以编译运行,但当我们在工程中
打开jni文件夹中的文件时,却发现会出现文件引用不到的错误,这是由于我们没有将NDK
的文件引用来的缘故,具体解决办法如下:
Windows->Prefrences->C/C++->Build->Environment
在右侧添加一个变量:
C_INCLUDE_PATH:
- ${NDK_HOME}/platforms/android-14/arch-arm/usr/include:${NDK_HOME}/sources/cxx-stl/stlport/stlport
最后Apply -> OK
至此问题解决了。
完。