资讯专栏INFORMATION COLUMN

JNI C/C++和Java的相互调用

lindroid / 1425人阅读

摘要:安卓中支持和语言,当使用到语言时,代码和如何交互就尤为重要。调用新建项目,创建如下类上面声明了两个方法,表示和的方法实现将在中给出。在目录下运行如下命令以生成对应的实现文件。

安卓中支持c++(NDK)和java(SDK)语言,当使用到c++语言时,c++代码和java如何交互就尤为重要。在下载的NDK包中samples/hello-jni有一个简单的实例可以参考。

java调用C++

新建Android项目,创建如下类:

package com.example.testjni;

public class TextJni {
    // support to c
    static {
        System.loadLibrary("jniinterface");
    }
    public static native int getInt();
    public static native String getString();
}

上面声明了两个native方法,表示getInt和getString的方法实现将在c++(libjniinterface.so)中给出。

在bin/classes目录下运行如下命令,以生成native对应的实现文件。

    javah com.example.testjni.TextJni
    # 注意如果要有Android SDK的类需要指定classpath, 如
    javah -classpath ~/dev/android/sdk/platforms/android-19/android.jar:./bin/classes com.togic.gameengine.GFRenderer

生成头文件拷贝出来,创建jni文件夹,并创建出cpp实现文件

com_example_testjni_TextJni.cpp:

#include 
#include 
#include "com_example_testjni_TextJni.h"

int sum ()
{
    int x,y;
    x = 100 ;
    y = 1000;
    x += y;
    return x;
}

//实现 com_example_textjni_textJNI.h 的方法
JNIEXPORT jint JNICALL Java_com_example_testjni_TextJni_getInt(JNIEnv * env, jclass cls)
{
    return sum();
}

JNIEXPORT jstring JNICALL Java_com_example_testjni_TextJni_getString(JNIEnv * env, jclass cls)
{
    return env->NewStringUTF("HelloNDK!");
}

这里要用到交叉编译,组织c++代码需要用Android.mk。

新建一个Android.mk文件在jni/下

Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := jniinterface
LOCAL_SRC_FILES := com_example_testjni_TextJni.cpp

#LOCAL_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)

然后就可以用NDK里的工具:ndk-build来生成动态链接库:libjniinterface.so

生成的库文件就可以被之前的Java文件调用了。

c++ 调用 java

可以在上例中getString方法里利用JNI调用java:

JNIEXPORT jstring JNICALL Java_com_togic_testjni2_TextJni_getString(JNIEnv * env, jclass cls)
{
    jclass TextJni;
    jobject instTextJni;
    jmethodID getCurrInt;

    JNIEnv* jniEnv = env;

    TextJni = jniEnv->FindClass("com/togic/testjni2/TextJni");

    jmethodID construction_id = jniEnv->GetMethodID(TextJni, "init", "()V");
    instTextJni = jniEnv->NewObject(TextJni, construction_id);

    getCurrInt = jniEnv->GetStaticMethodID(TextJni, "getCurrInt","()I");

    // call java static method
    jint jiref = jniEnv->CallStaticIntMethod(TextJni, getCurrInt);

    // clean
    jniEnv->DeleteLocalRef(TextJni);
    jniEnv->DeleteLocalRef(instTextJni);

    std::string strRef = "HelloNDK!" + view->getStaticString();
    return env->NewStringUTF(strRef.c_str());
}

首先值得注意的是jni.h里的函数区分c和c++语言两种接口,对于c++一般如下:

jclass clazz = env->FindClass(classname);

而对于c而言:

jclass clazz = (*env)->FindClass(env, classname);

GetMethodID中第三个参数表示方法签名,可以按如下方法获得:

javap -s 包名.类名   得到方法的签名
附 JNI数据类型转化

jstring 转 char *

const char nativeString = (env)->GetStringUTFChars(env, javaString, 0);

返回指向字符串的 UTF-8 字符数组的指针,该数组在被 ReleaseStringUTFChars() 释放前将一直有效。

(*env)->ReleaseStringUTFChars(env, javaString, nativeString); 

char * 转 jstring

jstring  jstr = (*env)->NewStringUTF(env, char *utf) 

利用 UTF-8 字符数组构造新 java.lang.String 对象。

其他类型

Java 类型 本地 c 类型 说明 
boolean jboolean 无符号,8 位 
byte jbyte 无符号,8 位 
char jchar 无符号,16 位 
short jshort 有符号,16 位 
int jint 有符号,32 位 
long jlong 有 符号,64 位 
float jfloat 32 位 
double jdouble 64 位 
void void N/A

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65397.html

相关文章

  • Step By Step_Java通过JNIC程序执行

    摘要:以下将以一个实际例子展示通过调用打印主要记录实现的过程和方法,对其中的一些原理和规范不做具体展开。指向在此代码中实例化的对象的一个句柄,相当于指针。加载本地共享库运行结果如下传递参数接下来看一下如何通过向传递参数。 showImg(https://segmentfault.com/img/remote/1460000008935007); 文章为本人编纂,转载请联系作者并注明出处。 在...

    mist14 评论0 收藏0
  • Andorid Studio NDK开发-Hello World

    摘要:介绍了在中配置的开发环境开发环境配置,开发环境配置完成之后,就要写一下著名的程序了。尤其是但是并不妨碍你使用其他语言,只要调用约定支持就可以了。是指定所在的目录,项目成功之后,会在目录里生成文件。是包名加上类名。 介绍了在Android Studio中配置NDK的开发环境:Android Studio NDK开发-环境配置,NDK开发环境配置完成之后,就要写一下著名的Hello Wor...

    melody_lql 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<