Как сделать правильный вызов с Android на нестатическую функцию в Java? (Cocos2Dx в смеси) - PullRequest
4 голосов
/ 05 марта 2012

Итак, я разрабатываю небольшой проект с Cocos2Dx, но я пытаюсь добавить функциональность Bluetooth, и это подразумевает вызов нестатического метода, чтобы получить доступ к ассоциации основной активности с API Android.Почти все, что я видел, подсказывает мне следовать этой процедуре: - Создать экземпляр основного действия (окружение-> NewGlobalRef - это то, что я использую) - Получить метод из действия и выполнить его (environment-> GetObjectClass)

А вот и код.В java у нас есть следующее (исключая такие логические вещи, как onCreate, onResume и т. Д.):

public class TSP extends Cocos2dxActivity{
    public void CnxAttempt(){
         Log.e("TSP_BT","aTTEMPTING!");
    }
}

Вот и все!Только сейчас я хочу показать только сообщение журнала, подтверждающее, что функция выполнена.Самое интересное в C ++:

    static JNIEnv* getJNIEnv(void){
    JNIEnv *env = 0;

    // get jni environment
    if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){
        CCLog("Failed to get the environment using GetEnv()");
    }

    if (gJavaVM->AttachCurrentThread(&env, 0) < 0){
        CCLog("Failed to get the environment using AttachCurrentThread()");
    }

    return env;
}
typedef struct JniMethodInfo_{
        JNIEnv *    env;        // The environment
        jclass      classID;    // classID
        jmethodID   methodID;   // methodID
    } JniMethodInfo;            // Struct that stores most of the important information to relate to Java code

    static bool getMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode){
        jmethodID methodID = 0;
        JNIEnv *pEnv = 0;
        jobject methodObject = NULL;

        bool bRet = false;

        do {
            pEnv = getJNIEnv();
            if (! pEnv){
                CCLog("getMethodInfo -- pEnv false");
                break;
            }

            jclass localRef = pEnv->FindClass("org/cocos2dx/tsp/TSP");
            if (localRef == NULL) {
                CCLog("getMethodInfo -- localRefCls false");
                 break; // exception thrown 
            }

            gCallbackObject = pEnv->NewGlobalRef(localRef);
            if (gCallbackObject == NULL){
                CCLog("getMethodInfo -- CallbackOBJ false");
                break;
            }

            jclass classID = pEnv->GetObjectClass(methodObject);
            if (!classID){
                CCLog("getMethodInfo -- classID false");
                break;
            }

            methodID = pEnv->GetMethodID(classID, methodName, paramCode);
            if (!methodID){
                CCLog("getMethodInfo -- methodID false");
                break;
            }
            methodinfo.classID = classID;
            methodinfo.env = pEnv;
            methodinfo.methodID = methodID;
            CCLog("getMethodInfo -- methodinfo created");
            bRet = true;
        } while(0);

        return bRet;
    }

    void CnxAttempt(){
        JniMethodInfo methodInfo; // Creating a JniMethodInfo object to store all the data

        if (! getMethodInfo(methodInfo, "CnxAttempt", "()V")){
            CCLog("getMethodInfo is FALSE :(");
            return;
        }
        methodInfo.env->CallVoidMethod(methodObject,methodInfo.methodID);
        methodInfo.env->DeleteLocalRef(methodInfo.classID);
    }

И все!При вызове CnxAttempt на C ++ он идет BOOM, потому что он не распознает метод в классе Java и не может добраться до него ... Кто-нибудь может мне помочь?Если что-то не понятно, пожалуйста, дайте мне знать.Большое спасибо заранее !!

1 Ответ

3 голосов
/ 06 марта 2012

Создание новой глобальной ссылки не создает создания нового объекта. Разница между локальными и глобальными ссылками (из документов):

Локальные ссылки действительны в течение всего времени вызова нативного метода и автоматически освобождаются после возврата нативного метода. Глобальные ссылки остаются действительными до тех пор, пока они не будут явно освобождены.

Если вы хотите вызвать нестатический метод к объекту, вам нужно либо передать объект нативному методу (если он существует - разве основное действие уже не существует?), Создайте новый, используя NewObject * функции, или вызывая некоторый фабричный метод.

Затем получите объект класса объекта, получите methodID и затем вызовите метод.

...