cocos2d 中使用jni C++ 調用 Java 方法

來源:互聯網
上載者:User

標籤:

1.單一資料型別例子

假設我們Java中有這麼一個open的靜態方法,它沒有參數,有一個int的傳回值。怎麼在C++中調用它呢?


package cb.CbCCBLE;public class CbCCBLECentralManager {    public static final String TAG = "CbCCBLECentralManager Android";    public static int open()    {    Log.d(TAG,"open");    return 1;    }}


下面就是下面具體的調用方法,痛點主要就是getStaticMethodInfo方法的傳入參數。 注意到cb/CbCCBLE/CbCCBLECentralManager,就是安卓的具體包名加上class名字,用中間都加‘/‘。"open"就是方法的名字,最後一個是傳入參數和輸出參數,比較完全符合才能找到這個java方法,括弧內是輸入參數,右邊跟著傳回值。

#if defined(ANDROID)#include "platform/android/jni/JniHelper.h"#include <jni.h>int CbCCBLECentralManager::open(){    JniMethodInfo minfo;    bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "open", "()I");    if (! isHave)    {        CCLOG("FAIL: CbCCBLECentralManager - open");        return 0;    }        int result = minfo.env->CallStaticIntMethod(minfo.classID, minfo.methodID);    return result;}#endif


參數和傳回值都會用特殊簡寫來代替,不是int,比如I代表int。完整的參數對於如下:

參數類型 參數簡寫
boolean Z
byte B
char C
short S
int I
long J
float F
double D
void V

表格中提到的簡單類型如果是多個的話用比如是:


public class CbCCBLECentralManager {    public static final String TAG = "CbCCBLECentralManager Android";    public static int open(int a, int b)    {    Log.d(TAG,"open");    return 1;    }}


C++調用就如下了:


JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "open", "()II");

注意下CallStaticIntMethod,因為我們調用的是靜態返回int的方法,所以用了這個,要根據調用的方法不同而使用不同的東西,具體參考:  http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp2556


2.看一個字串的例子,字串會有點麻煩:


Java:


public static int scanPeripheralWithName(String name, long duration)    {    Log.d(TAG,"scanPeripheralWithName name:" + name + " duration:" + duration);    return 1;    }

C++


int CbCCBLECentralManager::scanPeripheralWithName(std::string name, long duration){    JniMethodInfo minfo;    bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "scanPeripheralWithName", "(Ljava/lang/String;J)I");    if (! isHave)    {        CCLOG("FAIL: CbCCBLECentralManager - scanPeripheralWithName");        return 0;    }    jstring jname = minfo.env->NewStringUTF(name.c_str());    jlong jDuration = (long)duration;    int result = minfo.env->CallStaticIntMethod(minfo.classID, minfo.methodID,jname, jDuration);        return result;}

string是一個jobject,jobject要加L作為首碼,因為java中的string類完整+包名就是java/lang/String.所以string的完整就是 Ljava/lang/String,因為是jobject,所以用‘;‘作為結束。

要注意的是CallStaticIntMethod的最後2個參數,我們傳進去了一個jstring和一個jlong。什麼是jstring呢?是這樣的:

jni有自己的資料類型,一般是j開頭,用它們作為java 和 c++的中間媒體。


JNI Types Java Type
void void
jboolean boolean
jbyte byte
jchar char
jshort short
jint int
jlong long
jfloat float
jdouble double
jobject All Java objects
jclass java.lang.Class objects
jstring java.lang.String objects
jobjectArray Array of objects
jbooleanArray Array of booleans
jbyteArray Array of bytes
jshortArray Array of shorts
jintArray Array of integers
jlongArray Array of longs
jfloatArray Array of floats
jdoubleArray Array of doubles


3.看一個數組例子

返回字串的例子:

 public static String[] getAllPeripherals()    {        Log.d(TAG,"getAllPeripherals");        String[] resultArray = {"testPeripheral1", "testPeripheral2"}; //just for test        return resultArray;    }

std::vector<std::string> CbCCBLECentralManager::getAllPeripherals(){    std::vector<std::string> stdResult;        JniMethodInfo minfo;    bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "getAllPeripherals", "()[Ljava/lang/String;");    if (! isHave)    {        CCLOG("FAIL: CbCCBLECentralManager - getAllPeripherals");        //return stdResult;        return stdResult;    }        jobjectArray jResult = static_cast<jobjectArray>(minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID));    jsize resultSize = minfo.env->GetArrayLength(jResult);        jsize index = 0;    while(index < resultSize)    {        jstring eachElement = (jstring)minfo.env->GetObjectArrayElement(jResult, index);        std::string stdString = JniHelper::jstring2string(eachElement);        stdResult.push_back(stdString);        ++index;    }        return stdResult;}

數組前面要加上一個‘[‘, 這裡還用了些其他方法,像得到數組長度,根據index得到數組內容。


傳入字串的例子:

public static int scanPeripheralWithServiceUUIDs(String[] serviceUUIDs, long duration)    {       Log.d(TAG,"scanPeripheralWithServiceUUIDs:" + duration);    }

int CbCCBLECentralManager::scanPeripheralWithServiceUUIDs(std::vector<std::string>serviceUUIDs,long duration){    JniMethodInfo minfo;    bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "scanPeripheralWithServiceUUIDs", "([Ljava/lang/String;J)I");    if (! isHave)    {        CCLOG("FAIL: CbCCBLECentralManager - scanPeripheralWithServiceUUIDs");        return 0;    }    jint size = serviceUUIDs.size();    jclass StringObject = minfo.env->FindClass("java/lang/String");    jobjectArray jServiceUUIDsArray = minfo.env->NewObjectArray( size, StringObject, NULL);    jlong jDuration = (long)duration;    for(int i = 0; i < serviceUUIDs.size(); i++)    {        jstring serviceUUID = minfo.env->NewStringUTF(serviceUUIDs[i].c_str());        minfo.env->SetObjectArrayElement(jServiceUUIDsArray, i, serviceUUID);    }    int result = minfo.env->CallStaticIntMethod(minfo.classID, minfo.methodID, jServiceUUIDsArray, jDuration);        return result;}


4.看一個自訂class的例子


package OurBLE;public class OurBlePeripheralAdvertisementData{    public String deviceName;public String getDeviceName(){    return deviceName;    }}

比如說有這麼一個class作為jni如何傳遞呢?其實跟那個string類似。


 public static OurBlePeripheralAdvertisementData getPeripheralAdvertisementData(String peripheralId)    {        Log.d(TAG,"getPeripheralAdvertisementData");        OurBlePeripheralAdvertisementData result = new OurBlePeripheralAdvertisementData();        result.deviceName = "deviceName1";        return result;    }

CbCCBLEPeripheralAdvertisementData CbCCBLECentralManager::getPeripheralAdvertisementData(std::string peripheralId){    CbCCBLEPeripheralAdvertisementData data = CbCCBLEPeripheralAdvertisementData();    JniMethodInfo minfo;    bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "getPeripheralAdvertisementData", "(Ljava/lang/String;)LOurBLE/OurBlePeripheralAdvertisementData;");    if (! isHave)    {        CCLOG("FAIL: CbCCBLECentralManager - getPeripheralAdvertisementData");        return data;    }    jstring jPeripheralId = minfo.env->NewStringUTF(peripheralId.c_str());    jobject result = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID, jPeripheralId);        jclass CbCCBLEPeripheralAdvertisementDataClass = minfo.env->FindClass("OurBLE/OurBlePeripheralAdvertisementData");    jmethodID deviceNameMId = minfo.env->GetMethodID(CbCCBLEPeripheralAdvertisementDataClass, "getDeviceName", "()Ljava/lang/String;");      jstring jDeviceName = (jstring)minfo.env->CallObjectMethod(result, deviceNameMId);        //deviceName    data.deviceName = JniHelper::jstring2string(jDeviceName);    return data;}


主要這裡還用了些FindClass,GetMethodID, CallObjectMethod API,這樣class就能傳遞了。

jni真的是無所不能啊。 《cocos2d 中使用jni Java 調用 C++ 方法》

http://www.waitingfy.com/archives/1648

cocos2d 中使用jni C++ 調用 Java 方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.