[cocos2dx]在cocos2dx中通过Jni实现Java与C++的互相调用(二)
来源:互联网 发布:绅士仓库新域名 编辑:程序博客网 时间:2024/05/22 13:35
jni详解介绍
JNI是JVM实现中的一部分,因此Native语言和Java代码都运行在JVM的宿主环境。JNI的出现使得开发者既可以利用Java语言跨平台、类库丰 富、开发便捷等特点,又可以利用Native语言的高效。JNI是一个双向的接口:开发者不仅可以通过JNI在Java代码中访问Native模块,还可以在 Native代码中嵌入一个JVM,并通过JNI访问运行于其中的Java模块。可见,JNI担任了一个桥梁的角色,它将JVM与Native模块联系起来,从而实现了Java代码与Native代码的互访。如下图:
缺点:由于Native模块的使用,Java代码会丧失其原有的跨平台性和类型安全等特性。但是这不是我们应该担心的,不是吗?哈哈。也就是说,JNI是帮助游戏在Java代码中调用Native接口和在Native代码中调用Java接口。
方法1. 基本使用
c++接口,一般来说,要在Native代码中访问Java对象,有如下几个步骤:- 得到该Java对象的类定义。JNI定义了jclass 这个类型来表示Java的类的定义,并提供了FindClass接口,根据类的完整的包路径即可得到其jclass 。
- 根据jclass 创建相应的对象实体,即jobject 。在Java中,创建一个新对象只需要使用new 关键字即可,但在Native代码中创建一个对象则需要两步:首先通过JNI接口GetMethodID得到该类的构造函数,然后利用NewObject接口构造出该类的一个实例对象。
- 访问jobject 中的成员变量或方法。访问对象的方法是先得到方法的Method ID,然后使用CallMethod 接口调用,这里Type对应相应方法的返回值——返回值为基本类型的都有相对应的接口,如CallIntMethod;其他的返回值(包括String) 则为CallObjectMethod。可以看出,创建对象实质上是调用对象的一个特殊方法,即构造函数。访问成员变量的步骤一样:首先 GetFieldID得到成员变量的ID,然后Get/SetField读/写变量值。
方法2. jnihelper
2dx里面为我们提供了一个JniHelper类,来满足与Java层的数据交互,JniHelper可以很方便的调用java层的动静态方法。C++调用Java
JniUtil.h
#pragma once#include <string>using namespace std;namespace JniUtil{string callJava_getAppVersion();bool callJava_copyText(string copyText);string callJava_getTestAllString(bool b,int i,float f,double d,string s);void callJava_callNativeFunShowText(bool b,int i,float f,double d,string s);}
JniUtil.cpp
#include "JniUtil.h"#include "cocos2d.h"#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID#include <Jni.h>#include "platform/android/jni/JniHelper.h"#endif#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS#include "IosHelper.h"#endif#define JAVA_CLASSNAME "org/cocos2dx/cpp/AppActivity"using namespace cocos2d;namespace JniUtil{string callJava_getAppVersion(){string str = "";#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROIDJniMethodInfo minfo; //在org.cocos2dx.cpp.AppActivity文件中查找static String getAppVersion();这静态方法是否存在。bool isHave = JniHelper::getStaticMethodInfo(minfo,JAVA_CLASSNAME, "getAppVersion", "()Ljava/lang/String;");if (isHave) { jstring jVersion = (jstring)minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID); //使用jstring2string函数将返回的jstring类型的值转化为c++中的string类型 //string text = JniHelper::jstring2string(jVersion);const char* version = minfo.env->GetStringUTFChars(jVersion,0);str = version;minfo.env->ReleaseStringUTFChars(jVersion, version);minfo.env->DeleteLocalRef(minfo.classID); cocos2d::log("JniFun call callJava_getAppVersion over!===%s",str.c_str());} else{cocos2d::log("JniFun call callJava_getAppVersion error!");}#endif#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS//IosHelper::HuiPay(kStr.c_str());#endifreturn str;}bool callJava_copyText(string copyText){bool isSuccess = false;#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROIDJniMethodInfo minfo; bool isHave = JniHelper::getStaticMethodInfo(minfo,JAVA_CLASSNAME, "copyText", "(Ljava/lang/String;)Z");if (isHave) { jstring jCopyText = minfo.env->NewStringUTF(copyText.c_str());jboolean jIsSuccess= minfo.env->CallStaticBooleanMethod(minfo.classID, minfo.methodID,jCopyText); isSuccess = jIsSuccess;minfo.env->DeleteLocalRef(minfo.classID); cocos2d::log("JniFun call callJava_copyText over!");} else{cocos2d::log("JniFun call callJava_copyText error!");}#endif#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS//IosHelper::HuiPay(kStr.c_str());#endifreturn isSuccess;}string callJava_getTestAllString(bool b,int i,float f,double d,string s){string str = "";#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROIDJniMethodInfo minfo; bool isHave = JniHelper::getStaticMethodInfo(minfo,JAVA_CLASSNAME, "getTestAllString", "(ZIFDLjava/lang/String;)Ljava/lang/String;");if (isHave) { jstring js = minfo.env->NewStringUTF(s.c_str());jstring jRes = (jstring)minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID,b,i,f,d,js); const char* res = minfo.env->GetStringUTFChars(jRes,0);str = res;minfo.env->ReleaseStringUTFChars(jRes, res);minfo.env->DeleteLocalRef(js);minfo.env->DeleteLocalRef(minfo.classID); cocos2d::log("JniFun call callJava_getTestAllString over!==%s",str.c_str());} else{cocos2d::log("JniFun call callJava_getTestAllString error!");}#endif#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS//IosHelper::HuiPay(kStr.c_str());#endifreturn str;}void callJava_callNativeFunShowText(bool b,int i,float f,double d,string s){#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROIDJniMethodInfo minfo; bool isHave = JniHelper::getStaticMethodInfo(minfo,JAVA_CLASSNAME, "callNativeFunShowText", "(ZIFDLjava/lang/String;)V");if (isHave) { jstring js = minfo.env->NewStringUTF(s.c_str());jstring jRes = (jstring)minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID,b,i,f,d,js); const char* res = minfo.env->GetStringUTFChars(jRes,0);string str = res;minfo.env->ReleaseStringUTFChars(jRes, res);minfo.env->DeleteLocalRef(js);minfo.env->DeleteLocalRef(minfo.classID); cocos2d::log("JniFun call callJava_callNativeFunShowText over!==%s",str.c_str());} else{cocos2d::log("JniFun call callJava_callNativeFunShowText error!");}#endif#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS//IosHelper::HuiPay(kStr.c_str());#endif}}
Java调用C++
AppActivity.java
package org.cocos2dx.cpp;import org.cocos2dx.lib.Cocos2dxActivity;import org.cocos2dx.lib.Cocos2dxHelper;import android.content.ClipData;import android.content.ClipboardManager;import android.content.pm.PackageInfo;import android.os.Bundle;import android.util.AndroidException;import android.view.WindowManager;public class AppActivity extends Cocos2dxActivity //public class AppActivity extends Cocos2dxHelper {//在java类中定义一个方法,用于提供给java调用C++public static native void NativeFunShowText(String text);private static AppActivity appActivity = null; //剪切板管理工具类 private static ClipboardManager mClipboardManager; //剪切板Data对象 private static ClipData mClipData;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);appActivity = this;getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);mClipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);}public static String getAppVersion() throws AndroidException{PackageInfo pInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0);String version = pInfo.versionName +" "+ pInfo.versionCode;return version;}public static boolean copyText(String copyTxt){ //创建一个新的文本clip对象 mClipData = ClipData.newPlainText("Simple test", copyTxt);//把clip对象放在剪贴板中 mClipboardManager.setPrimaryClip(mClipData); return true;}public static String getTestAllString(boolean b,int i,float f,double d,String s){final String str = "bool:"+ b + " int:" + i + " float:" + f + " double:" + d + " String:" + s;System.out.println("----getTestAll----out runOnUiThread-----"+str);//添加到主线程appActivity.runOnUiThread(new Runnable(){public void run(){System.out.println("----getTestAll----in runOnUiThread-----"+str);}});return str;}public static void callNativeFunShowText(boolean b,int i,float f,double d,String s){final String str = "bool:"+ b + " int:" + i + " float:" + f + " double:" + d + " String:" + s;System.out.println("----callNativeFunShowText----out runOnGLThread-----"+str);//想从java代码来改变cocos2dxUI界面,需要在GL线程中运行,否则会崩溃appActivity.runOnGLThread(new Runnable(){public void run(){System.out.println("----callNativeFunShowText----in runOnGLThread-----"+str);NativeFunShowText(str);}});}}
JniCallback.h
#pragma oncenamespace JniCallback{}
JniCallback.cpp
#include "JniCallback.h"#include "cocos2d.h"#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID#include <Jni.h>#include "platform/android/jni/JniHelper.h"#endifusing namespace cocos2d;namespace JniCallback{extern "C" {#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID //Java_:是格式,必须加的//org_cocos2dx_cpp_AppActivity_NativeFunShowText:是包名+类名+方法名JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_NativeFunShowText (JNIEnv* env, jclass method, jstring param){const char* data = env->GetStringUTFChars(param, 0);cocos2d::log("Java_org_cocos2dx_cpp_AppActivity_NativeFunShowText---- :%s",data);//do cocosUI somethingenv->ReleaseStringUTFChars(param, data);}#endif}}
LOCAL_SRC_FILES := hellocpp/main.cpp \ hellocpp/test.cpp \ <--为新添加的可参考[cocos2dx]Android.mk学习
阅读全文
0 0
- [cocos2dx]在cocos2dx中通过Jni实现Java与C++的互相调用(二)
- [cocos2dx]在cocos2dx中通过Jni实现Java与C++的互相调用(一)
- cocos2dx通过Jni调用Android的Java
- cocos2dx 与android函数的互相调用及使用jni
- cocos2d-x中通过Jni实现Java与C++的互相调用
- cocos2d-x中通过Jni实现Java与C++的互相调用-------------------cocos2d-x-3.0正式版本(7.3)
- JNI JAVA与C的互相调用
- Cocos2dx之通过JNI实现c/c++和Android的java层函数互调
- cocos2dx 使用jni实现java调用c++
- cocos2dx 使用jni实现java调用c++
- Cocos2dx的C++和Java的互相调用(EasyNDK)
- 二、Cocos2dx中Android部分的c++和java实现相互调用(高级篇)
- VS2010 通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!
- Cocos2d-x游戏开发之Cocos2dx通过JNI调用Android的Java代码(webView实例)
- COCOS2DX与LUA互相调用使用方法
- Cocos2dx引擎笔记——如何让Java和C++接口互相调用:JNI使用指南
- 【iOS-cocos2d-X 游戏开发之十三】详细讲解在Xcode中利用预编译并通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!
- 【iOS-cocos2d-X 游戏开发之十三】详细讲解在Xcode中利用预编译并通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!
- QT中的d-pointer模式分析
- 网络游戏的对时以及同步问题
- 从经济学角度考虑结婚问题
- try-catch使用思考
- MySQL触发器入门
- [cocos2dx]在cocos2dx中通过Jni实现Java与C++的互相调用(二)
- kindeditor-4.1.10富文本编译器的使用
- 音视频学习路线 知乎答主
- 消息中间件 rabbitmq 级联-Federation
- stdin,stdout,stderr
- js开发: JavaScript 中的面向对象的初步理解
- matplotlib绘图基础--1
- 消息中间件 RabbitMQ 三种分布式架构区别 Clustering Federation Shovel
- 安装GeoServer并配置数据存储