我正在为Android安装SDL库,但我有一点障碍。
此函数在Java中定义:
/**
* This method is called by SDL using JNI.
* @return an array which may be empty but is never null.
*/
public static int[] inputGetInputDeviceIds(int sources) {
int[] ids = InputDevice.getDeviceIds();
int[] filtered = new int[ids.length];
int used = 0;
for (int i = 0; i < ids.length; ++i) {
InputDevice device = InputDevice.getDevice(ids[i]);
if ((device != null) && ((device.getSources() & sources) != 0)) {
filtered[used++] = device.getId();
}
}
return Arrays.copyOf(filtered, used);
}
在JNI / C方面:
/* returns number of found touch devices as return value and ids in parameter ids */
int Android_JNI_GetTouchDeviceIds(int **ids) {
JNIEnv *env = Android_JNI_GetEnv();
jint sources = 4098; /* == InputDevice.SOURCE_TOUCHSCREEN */
jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "inputGetInputDeviceIds", "(I)[I");
jintArray array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
int number = 0;
*ids = NULL;
if (array) {
number = (int) (*env)->GetArrayLength(env, array);
if (0 < number) {
jint* elements = (*env)->GetIntArrayElements(env, array, NULL);
if (elements) {
int i;
*ids = SDL_malloc(number * sizeof (**ids));
for (i = 0; i < number; ++i) { /* not assuming sizeof (jint) == sizeof (int) */
(*ids)[i] = elements[i];
}
(*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
}
}
(*env)->DeleteLocalRef(env, array);
}
return number;
}
现在这样可行,但我想编辑它以使调用非静态。我将Java端代码更改为:
public int[] inputGetInputDeviceIds(int sources) {
int[] ids = InputDevice.getDeviceIds();
int[] filtered = new int[ids.length];
int used = 0;
for (int i = 0; i < ids.length; ++i) {
InputDevice device = InputDevice.getDevice(ids[i]);
if ((device != null) && ((device.getSources() & sources) != 0)) {
filtered[used++] = device.getId();
}
}
return Arrays.copyOf(filtered, used);
}
从函数名中删除静态。
在JNI方面,我这样做:
/* returns number of found touch devices as return value and ids in parameter ids */
int Android_JNI_GetTouchDeviceIds(int **ids) {
JNIEnv *env = Android_JNI_GetEnv();
jint sources = 4098; /* == InputDevice.SOURCE_TOUCHSCREEN */
//jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "inputGetInputDeviceIds", "(I)[I");
//------------
jclass clazz = (*env)->FindClass(env, "org/libsdl/app/SDLActivity");
if (clazz == 0) {
__android_log_print(ANDROID_LOG_INFO, "SDL", "find class failed SDL_android.c line 1409");
return;
}
jmethodID javamethod = (*env)->GetMethodID(env, clazz, "inputGetInputDeviceIds", "(I)[I");
if (javamethod == 0) {
__android_log_print(ANDROID_LOG_INFO, "SDL", "find non static method failed SDL_android.c line 1414");
return;
}
__android_log_print(ANDROID_LOG_INFO, "SDL", "SUCCESS GETTING JNI METHOD FROM ENV SDL_android.c line 1416"); <-- i reach this line successfully
jintArray array = (*env)->CallObjectMethod(env, clazz, javamethod, sources); <-- this line segfaults
__android_log_print(ANDROID_LOG_INFO, "SDL", "made it to SDL_android.c line 1418");
if(array)
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "SUCCESS GETTING array line 1421");
}
else
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "FAILED GETTING array line 1425");
}
//------------
//jintArray array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
int number = 0;
*ids = NULL;
if (array) {
number = (int) (*env)->GetArrayLength(env, array);
if (0 < number) {
jint* elements = (*env)->GetIntArrayElements(env, array, NULL);
if (elements) {
int i;
*ids = SDL_malloc(number * sizeof (**ids));
for (i = 0; i < number; ++i) { /* not assuming sizeof (jint) == sizeof (int) */
(*ids)[i] = elements[i];
}
(*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
}
}
(*env)->DeleteLocalRef(env, array);
}
__android_log_print(ANDROID_LOG_INFO, "SDL", "reached the end of inputGetInputDeviceIds func");
return number;
}
出现此错误:
09-19 22:40:53.514: A/libc(29636): Fatal signal 11 (SIGSEGV) at 0x00000001 (code=1), thread 29650 (Thread-22463)
然后我重新编译c libs,清理项目并重新安装应用程序。代码段错误在那一行,而静态版本没问题。通过查看代码,此函数中没有其他静态引用。
可能导致该段错误的原因是什么? 我做了一些测试并更改了其他静态函数,抓住了获取类的env,查找函数并调用它实际上有效。
知道为什么这会失败?
答案 0 :(得分:2)
jintArray array = (*env)->CallObjectMethod(env, clazz, javamethod, sources);
^^^^^
This is incorrect
CallObjectMethod
的第二个参数不应该是jclass
,而是jobject
引用要调用该方法的该类的实例。
因此,您需要将SDLActivity
实例传递给C函数,以便C函数可以将其传递给CallObjectMethod
。