底下整理幾個常用的情況 :
1. 新增 C++ 檔案
2. 查看 Java Method Signature
3. Java 呼叫 C++ 函數
4. C++ 呼叫 Java 函數
5. Java 呼叫 C++ 時傳遞數字變數
6. C++ 呼叫 Java 時傳遞數字變數
7. Java 呼叫 C++ 時傳遞字串
8. C++ 呼叫 Java 時傳遞字串
9. Java 呼叫 C++ 時傳遞矩陣
10. C++ 呼叫 Java 時傳遞矩陣
11. Java 呼叫 C++ 時傳遞回呼函數
12. C++ 呼叫 Java 時傳遞回呼函數
1.
C++ 新增 .h/.cpp 檔案 :
i. 在 Classes 資料夾內新增
.h/.cpp 檔案
ii. 編輯
proj.android/jni/Android.mk :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cocos2dcpp_shared
LOCAL_MODULE_FILENAME := libcocos2dcpp
#新增的檔案加在 LOCAL_SRC_FILES
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/AMGamebarUtil.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
LOCAL_WHOLE_STATIC_LIBRARIES += chipmunk_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,cocos2dx)
$(call import-module,cocos2dx/platform/third_party/android/prebuilt/libcurl)
$(call import-module,CocosDenshion/android)
$(call import-module,extensions)
$(call import-module,external/Box2D)
$(call import-module,external/chipmunk)
2.
查看 Java Method Signature :
javap -s -classpath <path to jar file> <package name>.<class name>
javap -s -classpath ./AMGameBar.jar com.appmaster.AMCocos2dxInterface
javap -s com.appmaster.AMCocos2dxInterface (尚未壓縮成jar, 相對路徑 com/appmaster/AMCocos2dxInterface.class)
3.
Java 呼叫 C++ 函數 :
i. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
//1.定義
private static native void nativeLoginHandler();
...
static public void callNative(){
//2. 呼叫 c method
nativeLoginHandler();
}
}
ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
extern "C"
{
//c method 定義 :
//Java_<package name (replace point with under line)>_<class>_<method>
void Java_com_appmaster_AMCocos2dxInterface_nativeLoginHandler(JNIEnv* env, jobject thiz)
{
CCLOG("I HAVE BEEN TRIGGERED BY JAVA !");
}
...
}
4.
C++ 呼叫 Java 函數 :
i. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
JNIEnv *env =NULL;
jclass classid;
jmethodID methodid;
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
return;
}
//setup env
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (ret !=JNI_OK) {
env =NULL;
return;
}
classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
if (!classid){
return;
}
methodid =env->GetStaticMethodID(classid, "initGameBarLib", "()V");
if (!methodid){
return;
}
env->CallStaticObjectMethod(classid, methodid);
ii. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
static public void initGameBarLib(){
...
}
}
5.
Java 呼叫 C++ 時傳遞數字變數 :
i. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
private static native void nativeMethod(int val);
...
static public void run(){
nativeMethod(9527);
}
}
ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
extern "C"
{
void Java_com_appmaster_AMCocos2dxInterface_ nativeMethod(JNIEnv* env, jobject thiz, jint val)
{
int nval =(int)val;
CCLOG("val=%d", nval);
...
}
...
}
6.
C++ 呼叫 Java 時傳遞數字變數 :
i. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
JNIEnv *env =NULL;
jclass classid;
jmethodID methodid;
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
return;
}
//setup env
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (ret !=JNI_OK) {
env =NULL;
return;
}
classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
if (!classid){
return;
}
methodid =env->GetStaticMethodID(classid, "magicNumber", "(I)V");
if (!methodid){
return;
}
env->CallStaticObjectMethod(classid, methodid, (jint)9527);
ii. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
static public void magicNumber(int val){
...
}
}
7.
Java 呼叫 C++ 時傳遞字串 :
i. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
private static native void nativeMethod(final string data);
...
static public void run(){
nativeMethod("hello C++");
}
}
ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
extern "C"
{
void Java_com_appmaster_AMCocos2dxInterface_ nativeMethod(JNIEnv* env, jobject thiz, jstring data)
{
const char* pData =env->GetStringUTFChars(data, 0);
CCLOG("data=%s", pData);
...
env->ReleaseStringUTFChars(data, pData);
}
...
}
8.
C++ 呼叫 Java 時傳遞字串 :
i. C++ 檔案如下 :
#include <jni/JniHelper.h>
#include <jni.h>
...
JNIEnv *env =NULL;
jclass classid;
jmethodID methodid;
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
return;
}
//setup env
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (ret !=JNI_OK) {
env =NULL;
return;
}
classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
if (!classid){
return;
}
methodid =env->GetStaticMethodID(classid, "initGameBarLib", "(Ljava/lang/String;Ljava/lang/String;)V");
if (!methodid){
return;
}
jstring arg0 =env->NewStringUTF(pArg0); //char* pArg0
jstring arg1 =env->NewStringUTF(pArg1); //char* pArg1
env->CallStaticObjectMethod(classid, methodid, arg0, arg1);
env->DeleteLocalRef(arg0);
env->DeleteLocalRef(arg1);
ii. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
static public void initGameBarLib(String arg0, String arg1){
...
}
}
9.
Java 呼叫 C++ 時傳遞矩陣 :
i. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
private static native void nativeLoginHandler(int[] array);
...
static public void run(){
int[] array ={9, 5, 2, 7};
nativeLoginHandler(array);
}
}
ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
extern "C"
{
void Java_com_appmaster_AMCocos2dxInterface_nativeLoginHandler(JNIEnv* env, jobject thiz, jintArray ptr)
{
jsize length =env->GetArrayLength(ptr);
if (length>0){
jint* intarr =env->GetIntArrayElements(ptr, 0);
for (int i=0;i<length;++i){
printf("val[%d] =%d", i, intarr[i]);
}
env->ReleaseIntArrayElements(ptr, intarr, 0);
}
}
...
}
10.
C++ 呼叫 Java 時傳遞矩陣 :
i. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
int* praw_int =new int[4];
praw_int[0] =9;
praw_int[1] =5;
praw_int[2] =2;
praw_int[3] =7;
jintArray arrdata =env->NewIntArray(4);
env->SetIntArrayRegion(arrdata, 0, 4, (jint*)praw_int);
...
JNIEnv *env =NULL;
jclass classid;
jmethodID methodid;
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
return;
}
//setup env
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (ret !=JNI_OK) {
env =NULL;
return;
}
classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
if (!classid){
return;
}
methodid =env->GetStaticMethodID(classid, "initGameBarLib", "([II)V");
if (!methodid){
return;
}
env->CallStaticObjectMethod(classid, methodid, arrdata, 4);
delete [] praw_int;
}
ii. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
static public void initGameBarLib(int[] data, int num){
...
}
}
11.
Java 呼叫 C++ 時傳遞回呼函數 :
i. JAVA 檔案如下 :
package com.appmaster;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;
public class AMCocos2dxInterface
{
//傳遞回呼函數名稱 (字串)
private static native void nativeAsyncMethod(final string funcString);
...
static public void callbackFunc(){
//i will be callback from c++
}
static public void run(){
nativeAsyncMethod("callbackFunc");
}
}
ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>
...
extern "C"
{
void Java_com_appmaster_AMCocos2dxInterface_ nativeAsyncMethod(JNIEnv* env, jobject thiz, jstring funcString)
{
const char* pFuncString =env->GetStringUTFChars(funcString, 0);
...
//callback
JNIEnv *env =NULL;
jclass classid;
jmethodID methodid;
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
env->ReleaseStringUTFChars(funcString, pFuncString);
return;
}
//setup env
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (ret !=JNI_OK) {
env =NULL;
env->ReleaseStringUTFChars(funcString, pFuncString);
return;
}
classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
if (!classid){
env->ReleaseStringUTFChars(funcString, pFuncString);
return;
}
methodid =env->GetStaticMethodID(classid, pFuncString, "()V");
if (!methodid){
env->ReleaseStringUTFChars(funcString, pFuncString);
return;
}
env->CallStaticObjectMethod(classid, methodid);
env->ReleaseStringUTFChars(funcString, pFuncString);
}
...
}
12.
C++ 呼叫 Java 時傳遞回呼函數 :
(ps. 底下的實作並未真正的把 C function pointer 傳遞到 java 環境)
i. C++ (AMGamebarUtil.h)檔案如下 :
#include "cocos2d.h"
...
//定義回呼函數
typedef void (*onLoginCallback)(const cocos2d::CCString* pStrAccountID, const cocos2d::CCString* pStrNickname);
class AMGamebarUtil
{
public:
static void initGameBarLib(onLoginCallback pCBFunc1);
}
...
i. C++ (AMGamebarUtil.cpp)檔案如下 :
#include <jni/JniHelper.h>
#include <jni.h>
#include "AMGamebarUtil.h"
...
onLoginCallback pLC =NULL;
//預先建立 function 讓 java 回呼
extern "C"
{
void Java_com_appmaster_AMCocos2dxInterface_nativeLoginHandler(JNIEnv* env, jobject thiz, jstring aid, jstring nickname)
{
const char* pAid =env->GetStringUTFChars(aid, 0);
const char* pNick =env->GetStringUTFChars(nickname, 0);
//若是回呼函數已指定則回呼之
if (pLC !=NULL){
pLC(
cocos2d::CCString::createWithFormat("%s", pAid),
cocos2d::CCString::createWithFormat("%s", pNick)
);
}
env->ReleaseStringUTFChars(aid, pAid);
env->ReleaseStringUTFChars(nickname, pNick);
}
}
void AMGamebarUtil::initGameBarLib(onLoginCallback pCBFunc1)
{
//呼叫 JAVA
JNIEnv *env =NULL;
jclass classid;
jmethodID methodid;
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
CCLOG("Unity - AMGamebarUtil.cpp, Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
return;
}
//setup env
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (ret !=JNI_OK) {
env =NULL;
return;
}
if (env ==NULL){
return;
}
classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
if (!classid){
return;
}
methodid =env->GetStaticMethodID(classid, "initGameBarLib", "()V");
if (!methodid){
return;
}
//REGISTER CALLBACK FUNCTION
pLC =pCBFunc1;
//CALLING METHOD
env->CallStaticObjectMethod(classid, methodid);
}
i. C++ (.cpp)執行如下 :
//實作回呼函數
void onLoginCallbackHandler(const cocos2d::CCString* pStrAccountID, const cocos2d::CCString* pStrNickname)
{
CCLOG("onLoginCallbackHandler(), aid=%s, nickname=%s", pStrAccountID->getCString(), pStrNickname->getCString());
}
...
//實際呼叫 initGameBarLib 並傳遞回呼函數指標
AMGamebarUtil::initGameBarLib(&onLoginCallbackHandler);
ii. JAVA 檔案如下 :
public class AMCocos2dxInterface
{
//預先定義回呼之 c++ method
private static native void nativeLoginHandler(final String aid, final String nickname);
static public void initGameBarLib(){
...
//回呼 c++ method
nativeLoginHandler("THIS_IS_AID", "THIS_IS_NICKNAME");
}
...
}
ref:http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
ref:http://stackoverflow.com/questions/1232236/retrieving-byte-array-of-unknow-length-from-java-store
ref:http://www.lyceemermoz.com/iris/jlp/util/java/jdk/graphic/graphic.cpp
ref:http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html