2

I'm using the enum pattern to define a singleton in my application. I need to access methods of this singleton, but I can't seem to pass the singleton correctly.

I've tried passing the enum and creating a jobject as a globalRef out of it like this:

class FrameElapsedListener : public gkEngine::Listener{
public:
JNIEnv* env;
jobject entityManager;

FrameElapsedListener(JNIEnv* env, jobject entityManager) :
    env(env),
    entityManager(env->NewGlobalRef(entityManager)){}
~FrameElapsedListener(){
    env->DeleteGlobalRef(entityManager);
}
void tick(gkScalar rate);
};

but I got a crash when using it that the "local ref" was out of scope like this:

jclass entityManagerClass = env->FindClass(entityManagerClassPath.c_str());
jmethodID entityManagerFrameElapsedMethodId = env->GetMethodID(entityManagerClass, "frameElapsed", "(F)V");
env->CallVoidMethod(entityManager, entityManagerFrameElapsedMethodId, rate); //crashes here

Now I'm trying to just get the singleton out of the enum, but I'm not sure how to grab enum values like that. Any advice?

mpellegr
  • 3,072
  • 3
  • 22
  • 36
  • 1
    Some error checking in general would help. But, in particular, what is the return value of GetMethodID and did it throw a Java exception (check with `ExceptionCheck` and debug with `ExceptionDescribe`). – Tom Blodget Jun 20 '13 at 19:26

3 Answers3

0

You can't save a JNIEnv pointer for use in a different thread. You have to get a new one in the thread, by calling AttachCurrentThread().

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I am using the same thread. The second section is in tick, which is called from the same thread I grab the JNIEnv* from. – mpellegr Jun 21 '13 at 14:35
  • The evidence and your comment suggest otherwise. Who calls `tick()`? You also need to be aware that a `jclass` is-a `jobject` and may also need a global-reference regime. – user207421 Jun 22 '13 at 09:56
0

I was able to solve my problem by changing my method of ensuring a singleton from an enum with a single enum value, to a class with a private constructor, private instance, and a getInstance() method. I had read in other places that the JNI can not use Java enums natively, but I thought since Enum is a class, I could just treat it as an object. Apparently, that's not possible.

mpellegr
  • 3,072
  • 3
  • 22
  • 36
0

I have wrote a library which using Java Enum in C++ native code,I wrote a helper class which is simliar to yours,here it is,https://github.com/bugparty/jni_wifi_manager

bowman han
  • 1,097
  • 15
  • 25