cocos2d-x中使用JNI的调用JAVA方法

时间:2022-11-09 12:08:56

用cocos2d-x公布Android项目时。都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface)。JNI是JAVA的一个通用接口。旨在本地化语言(如C\C++)与JAVA语言进行交互。在交互过程成中,JAVA调用的是已编译好的本地化语言的二进制代码(如Windows下的dll。Linux下的so文件)。所以在交叉编译时看到Eclipse的控制台输出

[armeabi] SharedLibrary  : libcocos2dcpp.so

[armeabi] Install        : libcocos2dcpp.so => libs/armeabi/libcocos2dcpp.so

时就可以觉得cocos2d-x项目在Android平台编译成功,其原理就是生成这个二进制文件(动态连接库)与Android的本地语言———JAVA进行交互,而交互的过程须要一个中间的桥梁。这个桥梁就是JNI。

那么接下来就记录下怎样在cocos2d-x中用C++中使用JNI调用Java语言的中的成员方法或静态方法。

在cocos2d-x中有个已封装好的用于方便操作操作JNI的类——JniHelper,主要通过下面两个函数来获取JAVA类的信息。

static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);

顾名思义,第一个函数是获取静态方法的信息。第二个是获取成员方法的信息。其參数都是一致的各自是

methodinfo:JniMethodInfo类的引用

className:类的路径(即包名加类名)

methodName:方法名

paramCode:方法的參数类型和返回值类型

当中的第四个參数的编写规则大致例如以下:

(參数类型...)返回值类型。

编写规则能够參照oracle的官方文档 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html

在c++数据类型映射到java数据类型时已下面的一个联合体方式来定义

typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;

能够看到。这个union包括了映射JAVA的8个原声数据类型和一个自己定义类型。这样就囊括了JAVA全部的数据类型的映射。

并且。JAVA VM(JAVA虚拟机)还定义了一下的签名来表明JAVA的数据类型

Z    boolean

B    byte

C    char

S    shot

I    int

J    long

F    float

D    double

L fully-qualified-class;    fully-qualified-class(注意分号)

[type    type[]

(arg-types)ret-type    method type

举个样例来说

假设想调用一下的一个JAVA方法

long f(int n, String s, int[] arr);

那么第四个參数(paramCode)能够写为

(ILjava/lang/String;[I)J

当然,上面的命名规则也能够通过JAVA反编译来获取。

cocos2d-x中使用JNI的调用JAVA方法

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2luZ2FiY2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

从上图就能够看出一个类的全部方法签名。由此也解释了JAVA虚拟机在解析JAVA字节码时就是通过上面的方法签名来找到对应的方法入口地址。

接下来来測试通过JniHelper来帮助实现c++调用一个带有參数和返回值的静态JAVA方法的过程

1. 创建一个新的cocos2d-x项目。然后拿到Eclipse上去编译。编译完毕后编辑入口类,增加我们要測试的JAVA代码

package com.cocos2dx.TestJNI;

import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView; import android.os.Bundle; public class TestJNI extends Cocos2dxActivity{ protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
} public Cocos2dxGLSurfaceView onCreateView() {
Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
// TestJNI should create stencil buffer
glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8); return glSurfaceView;
} static {
System.loadLibrary("cocos2dcpp");
} /////////////////////////增加JAVA測试代码/////////////////////////
public static String staticMethod(int i, String str, double d) {
return "i: " + i + ", str: " + str + ", d: " + d;
}
}

2. 改动HelloWorldScene.cpp,增加jni的调用代码

#include "HelloWorldScene.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#endif
USING_NS_CC; CCScene* HelloWorld::scene() {
CCScene *scene = CCScene::create();
HelloWorld *layer = HelloWorld::create();
scene->addChild(layer);
return scene;
} bool HelloWorld::init() {
if (!CCLayer::init()) {
return false;
}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo methodInfo;
//推断方法是否存在
bool isExist = JniHelper::getStaticMethodInfo(methodInfo, "com/cocos2dx/TestJNI/TestJNI", "staticMethod", "(ILjava/lang/String;D)Ljava/lang/String;");
if(isExist) {
jint i = 0;
jdouble d = 1.22;
jstring str = methodInfo.env->NewStringUTF("Test Static Method");//创建
jstring s = (jstring)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, i, str, d);//调用Java方法
const char* c = methodInfo.env->GetStringUTFChars(s, 0);//将jstring转成字符指针
//把返回的字符串显示在屏幕中
CCLabelTTF* ttf = CCLabelTTF::create(c, "Arial", 30);
ttf->setPosition(ccp(300, 160));
this->addChild(ttf);
//释放内存
methodInfo.env->ReleaseStringUTFChars(s, c);
methodInfo.env->DeleteLocalRef(str);
}else {
CCLog("share error");
}
#endif
return true;
}

执行结果就能够看到调用成功:

cocos2d-x中使用JNI的调用JAVA方法

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2luZ2FiY2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

cocos2d-x中使用JNI的调用JAVA方法的更多相关文章

  1. cocos2d 中使用jni C&plus;&plus; 调用 Java 方法

    1.简单数据类型样例 如果我们Java中有这么一个open的静态方法,它没有參数,有一个int的返回值.怎么在C++中调用它呢? package cb.CbCCBLE; public class Cb ...

  2. NativeCode中通过JNI反射调用Java层的代码,以获取IMEI为例

    简单说,就是在NativeCode中做一些正常情况下可以在Java code中做的事儿,比如获取IMEI. 这种做法会使得静态分析Java层代码的方法失效. JNIEXPORT jstring JNI ...

  3. Android JNI之调用JAVA方法的返回类型签名

    从http://blog.csdn.net/lonelyroamer/article/details/7932787截取的 如何签名: 下面看看Sign签名如何写,来表示要取得的属性或方法的类型. 1 ...

  4. HAL中通过JNI调用java方法【转】

    转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...

  5. Android Studio NDK开发-JNI调用Java方法

    相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需 ...

  6. java native interface JNI 调用Java方法

    在上一篇文章中介绍了JNI.以及java调用JNI.这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你能够创建Java对象,get.set 静态(static)和 实例(instanc ...

  7. C通过JNI反向调用JAVA程序方法

    JNI反向调用JAVA程序 引述:上文讲过java线程---OS线程的关系,然后C怎样反向调用JAVA程序方法是我们这篇讲的重点 1.ThreadTest中添加run()方法 2.编译ThreadTe ...

  8. Jsp中如何通过Jsp调用Java类中的方法

    Jsp中如何通过Jsp调用Java类中的方法 1.新建一个项目,在src文件夹下添加一个包:如:cn.tianaoweb.com; 2.再在包中添加一个类:如 package com; public ...

  9. C&plus;&plus;调用JAVA方法详解

    C++调用JAVA方法详解          博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...

随机推荐

  1. 关于lambda表达式的一些学习——基于谓词筛选值序列

    今天看了一些关于lambda表达式的知识,然后对于Func<T,TResult>泛型委托不太熟悉,便查了查相关资料,又引出来了基于谓词筛选值序列这个对我来说的新鲜知识点,于是去查MSDN, ...

  2. session的生命周期

    Session存储在服务器端,一般为了防止在服务器的内存中(为了高速存取),Sessinon在用户访问第一次访问服务器时创建,需要注意只有访问JSP.Servlet等程序时才会创建Session,只访 ...

  3. Android进阶篇-线程分析&lpar;一&rpar;

    转载自:http://www.trinea.cn/android/java-android%E7%BA%BF%E7%A8%8B%E6%B1%A0/ 介绍new Thread的弊端及Java四种线程池的 ...

  4. GIS数据格式:Geodatabase

    转自:http://www.cnblogs.com/quansixiang/archive/2010/09/17/1829286.html 1  Geodatabase概念 Geodatabase是A ...

  5. 【RL-TCPnet网络教程】第40章&Tab;RL-TCPnet之TFTP客户端(精简版)

    第40章      RL-TCPnet之TFTP客户端 本章节为大家讲解RL-TCPnet的TFTP客户端应用,学习本章节前,务必要优先学习第38章的TFTP基础知识.有了这些基础知识之后,再搞本章节 ...

  6. 使用django发布带图片的网页&lpar;上&rpar;

    如何使用django发布带静态图片的网页呢? 在settings.py里加入下面内容 STATIC_ROOT = os.path.join(os.path.dirname(__file__),'sta ...

  7. java构建树形菜单递归工具类

    1.设计菜单实体 import java.util.List; public class Menu { //菜单id private Long id; //父节点id private Long par ...

  8. hihoCoder编程练习赛70

    题目1 : 数位翻转 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 n,你可以进行若干次操作,每次操作可以翻转 n 的二进制表示下的某一位,即将 0 变成 ...

  9. Chrome 屏蔽广告

    转载: http://blog.csdn.net/yenange/article/details/76145216 1. 上网站: http://www.adtchrome.com/ Chorme下载 ...

  10. nodejs sass安装报错一招解决

    背景: 这个问题不是一天两天了,有时候是网速不行,有时候是被墙了,有时候是github把node-sass的包转移目录导致下载失败. Cannot download "https://git ...