The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
(android)How to Define List<> in JNI
ancientli


Joined: 01 Jul 2015
Posts: 45
I want to implete below Java code in JNI.
List<BluetoothGattService> services = gatt.getServices();

I try below C code.
jmethodID mid = (*env)->GetMethodID(env, gatt, "getServices", "()[Landroid.bluetooth.BluetoothGattService;");
or
jmethodID mid = (*env)->GetMethodID(env, gatt, "getServices", "()Landroid.bluetooth.BluetoothGattService;");
or
jmethodID = (*env)->GetMethodID(env, gatt, "getServices", "()Ljava.util.List;");

They seems to have failed, what is the correct code?
(android)How to Define List<> in JNI
hardcoredaniel
Guest

I'm not 100% sure, but I think your 3rd line should be correct:

jmethodID = (*env)->GetMethodID(env, gatt, "getServices", "()Ljava.util.List;");

But IIRC, "gatt" should be a valid "jclass" reference, not a "jobject". You need to do sth. like

jclass cls = env->GetObjectClass(env, gatt);

(from my memory, not correct code) and then use "cls" instead of "gatt".

Hope it helps,

Regards,

Daniel




---------- Původní zpráva ----------
Od: ancientcc
Komu: SDL
Datum: 15. 4. 2016 1:53:18
Předmět: [SDL] (android)How to Define List<> in JNI
Quote:

I want to implete below Java code in JNI.
List<BluetoothGattService> services = gatt.getServices();

I try below C code.
jmethodID mid = (*env)->GetMethodID(env, gatt, "getServices", "()[Landroid.bluetooth.BluetoothGattService;");
or
jmethodID mid = (*env)->GetMethodID(env, gatt, "getServices", "()Landroid.bluetooth.BluetoothGattService;");
or
jmethodID = (*env)->GetMethodID(env, gatt, "getServices", "()Ljava.util.List;");

They seems to have failed, what is the correct code?

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
(android)How to Define List<> in JNI
ancientli


Joined: 01 Jul 2015
Posts: 45
I correct code based your suggest.
JNIEXPORT void JNICALL Java_org_libsdl_app_xxx(JNIEnv* env, jclass jcls, jobject gatt)
{
              jclass cls = (*env)->GetObjectClass(env, gatt);
              jmethodID mid = (*env)->GetMethodID(env, cls, "getServices", "()Ljava/util/List;");
              // Q1: In below call, second parameter require cls or gatt?
              jobject services_object = (*env)->CallObjectMethod(env, cls, mid);
              jclass services_cls = (*env)->GetObjectClass(env, services_object);

              // Above code looks like no error. services_cls is a valid pointer.
              // Q2: Below code hope to call list.size(). but returned mid is NULL! failed.
              mid = (*env)->GetMethodID(env, services_cls, "size", "()I");
              ......
}
Now I have two questions.
Q1: In the code motion, when get services_object, second parameter require cls or gatt?
Q2: How to call list.size()?
(android)How to Define List<> in JNI
hardcoredaniel
Guest

Hi,

your method declaration looks strange, it should be more like this:

JNIEXPORT void JNICALL Java_org_libsdl_app_xxx(JNIEnv* env, jobject jcls, jobject gatt)

but that's probably not relevant in your case, because you do not use the 2nd argument.

"CallObjectMethod" needs the object, not the class:

jobject services_object = (*env)->CallObjectMethod(env, gatt, mid);

I assume that once you have corrected this, then you should get a valid method ID for List.size().

Regards,

Daniel



---------- Původní zpráva ----------
Od: ancientcc
Komu: 'SDL Development List'
Datum: 16. 4. 2016 3:56:21
Předmět: Re: [SDL] (android)How to Define List<> in JNI
Quote:

I correct code based your suggest.
JNIEXPORT void JNICALL Java_org_libsdl_app_xxx(JNIEnv* env, jclass jcls, jobject gatt)
{
jclass cls = (*env)->GetObjectClass(env, gatt);
jmethodID mid = (*env)->GetMethodID(env, cls, "getServices", "()Ljava/util/List;");
// Q1: In below call, second parameter require cls or gatt?
jobject services_object = (*env)->CallObjectMethod(env, cls, mid);
jclass services_cls = (*env)->GetObjectClass(env, services_object);

// Above code looks like no error. services_cls is a valid pointer.
// Q2: Below code hope to call list.size(). but returned mid is NULL! failed.
mid = (*env)->GetMethodID(env, services_cls, "size", "()I");
......
}
Now I have two questions.
Q1: In the code motion, when get services_object, second parameter require cls or gatt?
Q2: How to call list.size()?


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
(android)How to Define List<> in JNI
ancientli


Joined: 01 Jul 2015
Posts: 45
Thanks! I have called List.size() successfully. But have new problem, can not get "get" method of List.

Below is Java code of hope.
{
            List<BluetoothGattService> services = gatt.getServices();
            int count = services.size();
            for (int i = 0; i < count; i ++) {
                        BluetoothGattService service = services.get(i);
            }
}

The following is corresponding JNI code.
{
            jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, gatt), "getServices", "()Ljava/util/List;");
            jobject services = (*env)->CallObjectMethod(env, gatt, mid);
            mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, services), "size", "()I");
            int count = (*env)->CallIntMethod(env, services, mid);
            int at;
            for (at = 0; at < count; at ++) {
                        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, services), "get", "(I)Landroid/bluetooth/BluetoothGattService;");
                        // Q: the got mid is null!
            }
}
Q: In the code motion, how to get "get" method of List?

On the other hand, why I use jclass to 2nd argument when declaration Java_org_libsdl_app_xxx? Because SDL code is so used, for example native functions in src/core/android/SDL_android.c.
(android)How to Define List<> in JNI
hardcoredaniel
Guest

Hi,

until your JNI code is working, I suggest to have one JNI call per line only and always check the results. This will imediately tell you where the error occurred, e.g. if it was jclass == NULL or jobject == NULL and so on. You can combine it later, once you know your code is working. Also the stack trace in the android log is more helpful then. Its also better readable. Plus in your for() - loop, you save the call to "GetObjectClass", because that can be done outside the loop.

As for your real problem, I don't really have a clue. Some answers at SO (like http://stackoverflow.com/questions/2228275/java-generics-and-jni) seem to explain a little more, but I have not fully understood it yet.

My best guess is that you can't ask for the class type you exect here:

mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, services), "get", "(I)Landroid/bluetooth/BluetoothGattService;");

but that you have to ask for Object instead:

mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, services), "get", "(I)Ljava/lang/Object;");

The object that you will receive after "CallObjectMethod" should still be of class android.bluetooth.BluetoothGattService.

Let me know if that works, I'm curious because it's just a guess.

Regards,

Daniel


---------- Původní zpráva ----------
Od: ancientcc
Komu: 'SDL Development List'
Datum: 18. 4. 2016 1:58:54
Předmět: Re: [SDL] (android)How to Define List<> in JNI
Quote:

Thanks! I have called List.size() successfully. But have new problem, can not get "get" method of List.

Below is Java code of hope.
{
List<BluetoothGattService> services = gatt.getServices();
int count = services.size();
for (int i = 0; i < count; i ++) {
BluetoothGattService service = services.get(i);
}
}

The following is corresponding JNI code.
{
jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, gatt), "getServices", "()Ljava/util/List;");
jobject services = (*env)->CallObjectMethod(env, gatt, mid);
mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, services), "size", "()I");
int count = (*env)->CallIntMethod(env, services, mid);
int at;
for (at = 0; at < count; at ++) {
mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, services), "get", "(I)Landroid/bluetooth/BluetoothGattService;");
// Q: the got mid is null!
}
}
Q: In the code motion, how to get "get" method of List?

On the other hand, why I use jclass to 2nd argument when declaration Java_org_libsdl_app_xxx? Because SDL code is so used, for example native functions in src/core/android/SDL_android.c.

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
(android)How to Define List<> in JNI
ancientli


Joined: 01 Jul 2015
Posts: 45
A Ha! I am glade to say that your guess is right! I have got "get" method of List using "Ljava/lang/Object". Next, calling methods of BluetoothGattService on it are also successful.

Function Java_org_libsdl_app_SDLActivity_nativeServicesDiscovered in https://github.com/freeors/SDL/blob/master/SDL2-2.0.4/src/peripheral/android/SDL_sysble.c is relative code, now it work. In this functon, there are tow list, List<BluetoothGattService> and List<BluetoothGattCharacteristic>.

If possible, want you to help me check whether there are problem in SDL_sysble.c, for example memory leak, grammar that not conform to the JNI specification.