2014-12-11 2 views
1

android/SDL C++ 코드로 자바 메소드를 호출하여 토스트를 팝업하거나 업데이트하려고합니다. 하지만C++에서 android 및 sdl로 자바 콜백

W/dalvikvm(4026): Invalid indirect reference 0x41e6b710 in decodeIndirectRef 

를 받고 오전 토스트 OK) (나의 메시지 문자열을 기록합니다 (정기적 처리기이라고에서. 예를 들면) 자바 측에서 업데이트 할 때 작동하는 것처럼 보이지만 즉시 설정 아무것도으로 (심지어 "Hello World") setText()에서 충돌이 발생합니다. 여기

#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 

#include "SDL.h" 

#include <android/log.h> 
#include <jni.h> 

#define log(...) __android_log_print(ANDROID_LOG_INFO, "SDL/c", __VA_ARGS__); 

void progressMessage(const char *message) 
{ 
    log("0) '%s'", message); 
    JNIEnv *jni_env = (JNIEnv*)SDL_AndroidGetJNIEnv(); 
    log("1) env %08x", (unsigned int)jni_env); 
    jobject jni_activity = (jobject)SDL_AndroidGetActivity(); 
    log("2) act %08x", (unsigned int)jni_activity); 

    jclass jni_class(jni_env->GetObjectClass(jni_activity)); 
    log("3) cls %08x", (unsigned int)jni_class); 
    jstring jstr = jni_env->NewStringUTF(message); 
    log("4) str %08x", (unsigned int)jstr); 
    jmethodID method = jni_env->GetMethodID(jni_class, 
    "progressMessage", "(Ljava/lang/String;)V "); 
    log("5) met %08x", (unsigned int)method); 

    jni_env->CallVoidMethod(jni_activity, method, jstr); 
    log("6) done"); 
    jni_env->DeleteLocalRef(jni_activity); 
    jni_env->DeleteLocalRef(jni_class); 
} 

int main(int argc, char *argv[]) 
{ 
    SDL_Window *window; 
    SDL_Renderer *renderer; 

    if(SDL_CreateWindowAndRenderer(0, 0, 0, &window, &renderer) < 0) 
     exit(2); 

    Uint8 done = 0; 
    SDL_Event event; 

    int loop = 0; 
    while(!done) 
    { 
     if (loop % 100 == 0) 
     { 
      char message[256]; 
      sprintf(message, "Log %d", loop); 
      progressMessage(message); 
     } 

     while(SDL_PollEvent(&event)) 
     { 
      if(event.type == SDL_QUIT || event.type == SDL_KEYDOWN || event.type == SDL_FINGERDOWN) 
      { 
       done = 1; 
      } 
     } 

     int col = loop % 512; 
     if (col > 255) 
      col = 256-col; 
     SDL_SetRenderDrawColor(renderer, col,col,col, 0xFF); 
     SDL_RenderClear(renderer); 
     SDL_RenderPresent(renderer); 
     SDL_Delay(10); 

     loop++; 
    } 

    exit(0); 
} 

내 클래스

package com.example.test; 

import android.util.Log; 
import android.widget.Toast; 
import android.os.Bundle; 

import org.libsdl.app.SDLActivity; 

public class SDLTest extends SDLActivity { 

    public static Toast toast = null; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     toast = Toast.makeText(this, "", Toast.LENGTH_SHORT); 

     this.progressMessage("Starting"); 
    } 

    public void progressMessage(String message) { 
     Log.i("SDL/java", message); 
     toast.setText(message); 
     toast.setDuration(Toast.LENGTH_SHORT); 
     toast.show(); 
    } 
} 

과 (https://wiki.libsdl.org/SDL_AndroidGetJNIEnv 기준)

내 main.cc는 그것은 '활동'포인터 것으로 나타나는 로그 캣 출력

I/SDL  (4561): SDL_Android_Init() 
I/SDL  (4561): SDL_Android_Init() finished! 
I/SDL/c (4561): 0) 'Log 0' 
I/SDL/c (4561): 1) env 76160ec8 
I/SDL/c (4561): 2) act 2d900009 
I/SDL/c (4561): 3) cls 1dd00011 
I/SDL/c (4561): 4) str 1d200015 
I/SDL/c (4561): 5) met 6d788688 
I/SDL/java(4561): Log 0 
I/SDL/c (4561): 6) done 
I/ActivityManager( 594): Displayed com.example.test/.SDLTest: +218ms 
V/SDL  (4561): onWindowFocusChanged(): true 
I/SDL/c (4561): 0) 'Log 100' 
I/SDL/c (4561): 1) env 76160ec8 
I/SDL/c (4561): 2) act 1de00011 
I/SDL/c (4561): 3) cls 2da00009 
I/SDL/c (4561): 4) str 1dc00019 
I/SDL/c (4561): 5) met 6d788688 
I/SDL/java(4561): Log 100 
I/SDL/c (4561): 6) done 
I/SDL/c (4561): 0) 'Log 200' 
I/SDL/c (4561): 1) env 76160ec8 
I/SDL/c (4561): 2) act 41e64a80 
W/dalvikvm(4561): Invalid indirect reference 0x41e64a80 in decodeIndirectRef 
I/dalvikvm(4561): "SDLThread" prio=5 tid=11 RUNNABLE 
I/dalvikvm(4561): | group="main" sCount=0 dsCount=0 obj=0x41e75fd0 self=0x761607a0 
I/dalvikvm(4561): | sysTid=4579 nice=0 sched=0/0 cgrp=apps handle=1981156344 
I/dalvikvm(4561): | state=R schedstat=(0 0 0) utm=3 stm=11 core=1 
I/dalvikvm(4561): at org.libsdl.app.SDLActivity.nativeInit(Native Method) 
I/dalvikvm(4561): at org.libsdl.app.SDLMain.run(SDLActivity.java:915) 
I/dalvikvm(4561): at java.lang.Thread.run(Thread.java:841) 
I/dalvikvm(4561): 
E/dalvikvm(4561): VM aborting 

입니다 손상되었습니다.

무엇 내가 놓친

(나는 또한 ENV, 활동, 클래스와 메소드가 모두 캐시 할 수 바라고 있어요)?

+0

main() 함수가 있습니다. 필자는 SDL에 익숙하지 않지만 main() 함수는 호출되지 않고 Java에서 네이티브 함수가 호출됩니다. 두 번째로, 모든 UI 항목은 기본 스레드 (여기에는 축배 포함)에서 액세스해야합니다. 다른 스레드에서 액티비티에 액세스하려고하면 문제가 발생할 수 있습니다. – 18446744073709551615

+0

안녕하세요, SDL은 모든 jni 시작을 처리하고 main()을 호출하는 SDLActivity를 제공합니다. 내 프레임 워크는 http://www.dinomage.com/2013/01/howto-sdl-on-android/을 기반으로했습니다. –

답변

1

이것은 스레드 문제입니다.

SDL은 별도의 스레드에서 SDLMain()을 시작하므로 해당 Java 메소드를 호출하는 것이 문제가됩니다! 여기 http://theorangeduck.com/page/issues-sdl-ios-and-android

를 언급하지만 SDLActivity

public boolean sendCommand(int command, Object data) 

에 인 sendCommand를 노출 할 수있는 메시지 시스템을 구현하여 내 즉각적인 문제를 해결 한 것처럼

이상적인 솔루션은 일부 나사산 모드에서 SDL을 실행하는 것입니다 processing by

public void progressMessage(String message) { 
    toast.setText(message); 
    toast.setDuration(Toast.LENGTH_LONG); 
    toast.show(); 
} 

public static boolean sendCommand(int command, String string) { 
    return SDLActivity.mSingleton.sendCommand(command, string); 
} 

@Override 
protected boolean onUnhandledMessage(int command, Object param) { 
    boolean ok = true; 
    switch (command) { 
    case COMMAND_USER_PROGRESS: 
     progressMessage((String)param); 
     break; 
    default: 
     ok = false; 
     break; 
    } 
    return ok; 
}