多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > Cocos2d-x3.3RC0通過JNI實現Java與C++互調

Cocos2d-x3.3RC0通過JNI實現Java與C++互調

來源:程序員人生   發布時間:2014-11-06 09:44:16 閱讀次數:2792次

1、JNI

JNI(Java Native Interface):Java的本地調用。本文通過JNI在Cocos2d-x3.3RC0中完成Java與C++的互調。具體實現以下兩個功
能:(1)通過Android sdk的API得到利用程序的包名,并傳遞給C++層函數。(2)通過C++函數調用Android的Java層函數,顯示1個對話框。點擊按鈕退出程序。
詳細知識見:http://blog.csdn.net/yuxikuo_1/article/details/39577257。其中最重要的是JNIEnv,這是1個C結構體。封裝了許多
經常使用函數:具體以下:
struct _JNIEnv {     /* do not rename this; it does not seem to be entirely opaque */     const struct JNINativeInterface* functions;   #if defined(__cplusplus)       jint GetVersion()     { return functions->GetVersion(this); }       jclass DefineClass(const char *name, jobject loader, const jbyte* buf,         jsize bufLen)     { return functions->DefineClass(this, name, loader, buf, bufLen); }       jclass FindClass(const char* name)     { return functions->FindClass(this, name); } // 這里省略其他函數...   }
Cocos2d-x對jni的操作進行了封裝,提供JniHelper類解決Java與C++的通訊。
下面介紹兩個經常使用的函數:

1、getStaticMethodInfo:

        用來判斷java類中靜態函數是不是存在,初始化結構體JniMethodInfo。該結構體封裝了JNIEnv*和java.lang.Class、函數ID。這樣可使用JNIEnv*調用CallStaticXXXMethod(jclass clazz,jmethodID methodID,...)和CallXXXMethod(jobject obj,jmethodID methodID,...)等經常使用函數,其中XXX代表函數返回值類型,如void、int等。以下代碼:參數1:JniMethodInfo,參數2:類的絕對路徑,該路徑為:proj.android/src/下的目錄,例如引擎模板工程下的路徑為:src/org/cocos2dx/cpp/XXX。XXX為cpp下的java文件。記住路徑中不用加.java后綴,由于路徑使用的是類名。參數3:函數名,參數4:函數簽名,具體規則見3類型簽名

JniMethodInfo info; bool ret = JniHelper::getStaticMethodInfo(info,"org/cocos2dx/cpp/AppActivity","getObj","()Ljava/lang/Object;"); jobject jobj; if(ret) { log("call void getObj() succeed"); jobj = info.env->CallStaticObjectMethod(info.classID,info.methodID); } bool re = JniHelper::getMethodInfo(info,"org/cocos2dx/cpp/AppActivity","func1","()V"); if(re) { log("call func1 succeed"); info.env->CallVoidMethod(jobj,info.methodID); }

2、getMethodInfo:用于調用Java類的非靜態函數


#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo info; //判斷org/cocos2dx/cpp/AppActivity.java中是不是存在getObj靜態函數 bool ret = JniHelper::getStaticMethodInfo(info,"org/cocos2dx/cpp/AppActivity","getObj","()Ljava/lang/Object;"); jobject jobj;//用于寄存返回的對象 if(ret) { log("call void getObj() succeed"); jobj = info.env->CallStaticObjectMethod(info.classID,info.methodID);//調用getObj函數,返回1個對象 } //判斷org/cocos2dx/cpp/AppActivity.java中是不是存在func1非靜態函數 bool re = JniHelper::getMethodInfo(info,"org/cocos2dx/cpp/AppActivity","func1","()V"); if(re) { log("call func1 succeed"); info.env->CallVoidMethod(jobj,info.methodID);//通過返回的對象調用非靜態函數 } #endif

3、類型簽名

類型簽名 Java類型
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L full-qualified-class; 完全限定的類
[ type type[ ]
(arg-types) ret-type 方法類型

        如java方法:long f(int n,String s,int[] arr); 類型簽名為:(ILjava/lang/String;[I)J。注意L后的分號,[是半開的,要與類型簽名完全1致。

2、具體步驟

1、創建Cocos2d-x3.3RC0工程

這個不做過量介紹,既然研究到Jni了,相比都不是太菜鳥了。

2、ADT與XCode分別導入工程

3、Xcode的Class目錄下添加JniTest類


JniTest.h代碼以下:JniTest.cpp暫時沒有代碼
#ifndef __JniDemo__JniTest__ #define __JniDemo__JniTest__ #include "cocos2d.h" USING_NS_CC; //定義兩個C++方法,在Jni的test.h中被Java方法調用。 //該方法被Java_org_cocos2dx_cpp_JniTestHelper_setPackageName調用 //定義org/cocos2dx/cpp/JniTestHelper類中的setPackageName方法 void setPackageName(const char* packageName) { log("packageName = %s",packageName); } //該方法被Java_org_cocos2dx_cpp_JniTestHelper_exitApp調用 //定義org/cocos2dx/cpp/JniTestHelper類中得exitApp函數 void exitApp() { Director::getInstance()->end(); } #endif /* defined(__JniDemo__JniTest__) */

然后在HelloWorldScene.cpp中包括以下頭文件,并在menuCloseCallback中添加以下代碼:
//頭文件包括,判斷平臺 #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include "../proj.android/jni/hellocpp/test.h"//1定是相對路徑 #endif //調用C++調用Java層代碼 void HelloWorld::menuCloseCallback(Ref* pSender) { #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) showTipDialog("exit","Exit,Really Go?"); #endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif }

4、Jni層代碼

打開ADT工程目錄下的jni/hellocpp/列表,在hellocpp下添加c++類,test.cpp和test.h。代碼以下:1定包括extern "C"
</pre><p class="p1"><pre name="code" class="cpp">#ifndef TEST_H_ #define TEST_H_ extern "C" { //C++調Java的函數接口,該方法在HelloWorldScene中menuCallback函數中使用。 void showTipDialog(const char* title,const char* msg); } #endif

test.cpp代碼以下:

#include "test.h" #include "cocos2d.h" #include "platform/android/jni/JniHelper.h" #include "../../../Classes/JniTest.h" #include <jni.h> #define CLASS_NAME "org/cocos2dx/cpp/JniTestHelper" using namespace cocos2d; extern "C" { //C++調Java的函數,在HelloWorldScene中的menuCallback函數中調用。 void showTipDialog(const char* title,const char* msg) { JniMethodInfo t; //判斷CLASS_NAME的類中是不是存在showTipDialog函數,如果存在,則調用。 if(JniHelper::getStaticMethodInfo(t,CLASS_NAME,"showTipDialog","(Ljava/lang/String;Ljava/lang/String;)V")) { jstring jTitle = t.env->NewStringUTF(title); jstring jMsg = t.env->NewStringUTF(msg); t.env->CallStaticVoidMethod(t.classID,t.methodID,jTitle,jMsg); t.env->DeleteLocalRef(jTitle); t.env->DeleteLocalRef(jMsg); } } //Java調C++函數,Java函數來自org/cocos2dx/cpp/JniTestHelper的java類。同時該函數為JniTestHelper的java類中setPackageName原生方法的定義 void Java_org_cocos2dx_cpp_JniTestHelper_setPackageName(JNIEnv* env,jobject thiz,jstring packageName) { const char* pkgName = env->GetStringUTFChars(packageName,NULL); setPackageName(pkgName);//此處調用的是Class目錄下JniTest類中的函數 env->ReleaseStringUTFChars(packageName,pkgName); } //同上,該函數定義了JniTestHelper的java類中的exitApp原生函數。 void Java_org_cocos2dx_cpp_JniTestHelper_exitApp(JNIEnv* env,jobject thiz) { exitApp();//此處調用的時Class目錄中JniTest類中的函數。 } }

5、Java層函數

在ADT工程目錄src/org.cocos2dx.cpp的目錄下添加java類,JniTestHelper.java
1)JniTestHelper.java代碼以下:
#include "test.h" #include "cocos2d.h" #include "platform/android/jni/JniHelper.h" #include "../../../Classes/JniTest.h" #include <jni.h> #define CLASS_NAME "org/cocos2dx/cpp/JniTestHelper" using namespace cocos2d; extern "C" { //C++調Java的函數,在HelloWorldScene中的menuCallback函數中調用。 void showTipDialog(const char* title,const char* msg) { JniMethodInfo t; //判斷CLASS_NAME的類中是不是存在showTipDialog函數,如果存在,則調用。 if(JniHelper::getStaticMethodInfo(t,CLASS_NAME,"showTipDialog","(Ljava/lang/String;Ljava/lang/String;)V")) { jstring jTitle = t.env->NewStringUTF(title); jstring jMsg = t.env->NewStringUTF(msg); t.env->CallStaticVoidMethod(t.classID,t.methodID,jTitle,jMsg); t.env->DeleteLocalRef(jTitle); t.env->DeleteLocalRef(jMsg); } } //Java調C++函數,Java函數來自org/cocos2dx/cpp/JniTestHelper的java類。同時該函數為JniTestHelper的java類中setPackageName原生方法的定義 void Java_org_cocos2dx_cpp_JniTestHelper_setPackageName(JNIEnv* env,jobject thiz,jstring packageName) { const char* pkgName = env->GetStringUTFChars(packageName,NULL); setPackageName(pkgName);//此處調用的是Class目錄下JniTest類中的函數 env->ReleaseStringUTFChars(packageName,pkgName); } //同上,該函數定義了JniTestHelper的java類中的exitApp原生函數。 void Java_org_cocos2dx_cpp_JniTestHelper_exitApp(JNIEnv* env,jobject thiz) { exitApp();//此處調用的時Class目錄中JniTest類中的函數。 } }

2)AppActivity.java代碼

package org.cocos2dx.cpp; import org.cocos2dx.lib.Cocos2dxActivity; import org.cocos2dx.lib.Cocos2dxGLSurfaceView; import org.cocos2dx.lib.Cocos2dxHandler.DialogMessage; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; import android.os.Message; public class AppActivity extends Cocos2dxActivity{ public static final int SHOW_DIALOG = 0x0001; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); JniTestHelper.init(mHandler); //調用JniTestHelper的setPackageName函數,setPackageName函數在test.cpp中定義,終究調用C++層的setPackageName方法 JniTestHelper.setPackageName(this.getPackageName()); } public Cocos2dxGLSurfaceView onCreateView(){ Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this); glSurfaceView.setEGLConfigChooser(5,6,5,0,16,8); return glSurfaceView; } static { System.loadLibrary("cocos2dcpp"); } private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case SHOW_DIALOG: DialogMessage dm = (DialogMessage)msg.obj; new AlertDialog.Builder(AppActivity.this) .setTitle(dm.titile) .setMessage(dm.message).setNegativeButton("cancle", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { // TODO Auto-generated method stub arg0.dismiss(); } }) .setPositiveButton("Ok",new DialogInterface.OnClickListener(){ public void onClick(DialogInterface arg0, int arg1) { arg0.dismiss(); JniTestHelper.exitApp();//調用JniTestHelper的exitApp函數,exitApp函數在test.cpp中定義,終究調用C++層的exitApp方法 } }) .create().show(); break; } } }; }



好了,代碼和注釋基本就結束了,還需要該的是Android.mk文件。代碼以下:
LOCAL_SRC_FILES := hellocpp/main.cpp hellocpp/test.cpp //將新建的test.cpp類加入mk文件 ../../Classes/AppDelegate.cpp ../../Classes/HelloWorldScene.cpp
之前介紹過萬能mk文件生成方法,詳見http://blog.csdn.net/yuxikuo_1/article/details/39552431。為了減少出問題的概率,建議改高AndroidManifest中的SDK版本,不改無所謂也。

6、工程總目錄


3、編譯運行

如出現問題可參考
1)http://blog.csdn.net/yuxikuo_1/article/details/39654499
2)http://blog.csdn.net/yuxikuo_1/article/details/39552639
3)http://blog.csdn.net/yuxikuo_1/article/details/39671733
注:環境Mac  XCode6  ADT22.2.1  Cocos2d-x3.3RC0  紅米Note。


4、源碼

說了這么多,沒有源碼那不是坑爹么。源碼連接:http://pan.baidu.com/s/1jGn80QE
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 日韩视频在线一区 | 国产亚洲精品久久久久久久 | 国内精品久久精品 | 91精品一区二区三区在线播放 | 欧美精品成人a多人在线观看 | 中文字幕网站在线 | 福利视频一区 | 叼嘿视频在线观看免费 | 国产成人久久久精品毛片 | 欧美不卡视频 | 波多野结衣中文字幕在线视频 | 一本伊大人香蕉久久网手机 | 色性综合 | 亚洲爱色 | 2020国产精品| 三级国产在线观看 | 国产精品久久久久亚洲 | 精品久久久日韩精品成人 | 日本久操 | 亚洲精品一区二区三区在线观看 | 日本高清2019免费视频 | 视频在线免费 | 亚洲欧洲无码一区二区三区 | 亚洲欧洲高清 | 中文字幕 亚洲 一区二区三区 | 在线国产视频观看 | 欧美日韩午夜视频 | 成人午夜视频一区二区国语 | 亚洲色域网 | 最近免费中文字幕mv | 又污又黄又无遮挡网站 | 亚洲图片一区二区三区 | 亚洲国产成人久久一区www妖精 | xxxxx性中国hd| 欧美a一片xxxx片 | 2022在线精品视频网站 | 亚洲免费色视频 | 免费区欧美一级毛片精品 | 1000部禁止18观看视频在线看 | 久久国产大片 | 亚洲在线观看一区 |