关于JNI的使用总结

  今天刚整了一下JNI,在百度上看了好多博客,好像在遇到问题方面解释的都比较少,安卓应用程序使用ndk开发的时候就使用了JNI,而且cocos2d-x移植到安卓平台的时候也有JNI的使用。

  废话不多说,贴代码,对了,这个例子是在别的博客上看到了,但是他没有解释错误的方面

public class Sample1 {
    public native int intMethod(int n);
    public native boolean booleanMethod(boolean bool);//因为这个都是没有实现的,所以加上native,感觉跟c++里面方法的声名类似
    public native String stringMethod(String text);
    public native int intArrayMethod(int[] intArray);
   
    public static void main(String[] args) {
        System.loadLibrary("Sample1");//这个函数用来加载在windows平台的Sample1.dll,就是接下来就说的生成的动态链接库
        Sample1 sample = new Sample1();
        int square = sample.intMethod(5);
        boolean bool = sample.booleanMethod(true);
        String text = sample.stringMethod("Java");
        int sum = sample.intArrayMethod(new int[]{1,2,3,4,5,8,13});
         
        System.out.println("intMethod: " + square);
        System.out.println("booleanMethod: " + bool);
        System.out.println("stringMethod: " + text);
        System.out.println("intArrayMethod: " + sum);
    }
}

然后javac得到.class文件,接着用javah -classpath . Sample1得到Sample1.h头文件 -classpath 是指定文件所在目录,一个点就代表当前目录,贴出Sample1.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Sample1 */

#ifndef _Included_Sample1
#define _Included_Sample1
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Sample1
 * Method:    intMethod
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_Sample1_intMethod
  (JNIEnv *, jobject, jint);

/*
 * Class:     Sample1
 * Method:    booleanMethod
 * Signature: (Z)Z
 */
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
  (JNIEnv *, jobject, jboolean);

/*
 * Class:     Sample1
 * Method:    stringMethod
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
  (JNIEnv *, jobject, jstring);

/*
 * Class:     Sample1
 * Method:    intArrayMethod
 * Signature: ([I)I
 */
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
  (JNIEnv *, jobject, jintArray);

#ifdef __cplusplus
}
#endif
#endif

然后贴出实现的代码

#include "Sample1.h"
#include <string>
#include <string.h>
#include <algorithm>
 
JNIEXPORT jint JNICALL Java_Sample1_intMethod
  (JNIEnv *env, jobject obj, jint num)
{
    return num * num;
}
 
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
  (JNIEnv *env, jobject obj, jboolean boolean)
{
    return !boolean;
}
 
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
  (JNIEnv *env, jobject obj, jstring string)
{
    const char* str = env->GetStringUTFChars(string, 0);
    char cap[128];
	strcpy_s(cap, str);
    env->ReleaseStringUTFChars(string, 0);
	std::string strs(cap);
	std::transform(strs.begin(), strs.end(), strs.begin(), toupper);
    return env->NewStringUTF(strs.c_str());
}
 
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
  (JNIEnv *env, jobject obj, jintArray array)
{
    int i, sum = 0;
    jsize len = env->GetArrayLength(array);
    jint *body = env->GetIntArrayElements(array, 0);
     
    for (i = 0; i < len; ++i)
    {
        sum += body[i];
    }
    env->ReleaseIntArrayElements(array, body, 0);
    return sum;
}

这里的env使用的方法是固定的,JNIEnv提供了很多在java和c++之间数据转换的方法

这里我使用vs2013生成动态链接库,生成动态链接库的时候要注意,如果使用的是64位的机子,那可能会报Can't load IA 32-bit .dll on a AMD 64-bit platform这个错误,原因就是字面上的意思,怎么生成64位的库呢

生成-->配置管理器-->活动平台解决方案。把从此处复制选择为x64,然后把平台选择为x64,然后重新生成就可以生成64位的动态链接库了

还有一个比较坑爹的错误找不到或无法加载主类 Sample1,这个出现的原因好像是classpath最后少了一个分号,也许你认为你的classpath是正确的,但是真的就是缺少了最后面一个分号;

最后成功了之后就会正常输出了


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值