通过 JNI 从 C 调用 Java 可变参数函数
Calling a Java variadic function from C through the JNI
我目前正在为我使用的 C 库创建一些 Java 绑定。我们的一个 C 结构有一个字符缓冲区,它是一个文件系统路径。调用 C 函数后,缓冲区被正确填充。我想获取缓冲区并将其转换为 Java 对象上的 java.nio.file.Path
成员。
不过我遇到了一些麻烦。我出于某种原因在 C 中生成了一个 NullPointerException
,但我看不出问题所在。
创建 java.nio.file.Path
对象的方法是通过 java.nio.file.Paths::get()
。
这里是相关的C代码:
const jclass paths_class = (*env)->FindClass(env, "java/nio/file/Paths");
if ((*env)->ExceptionCheck(env))
return;
const jmethodID get_method = (*env)->GetStaticMethodID(
env, paths_class, "get", "(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;");
if ((*env)->ExceptionCheck(env))
return;
const jstring path_str = (*env)->NewStringUTF(env, info.mi_path);
if ((*env)->ExceptionCheck(env))
return;
const jobject path_obj =
(*env)->CallStaticObjectMethod(env, paths_class, get_method, path_str); // exception generated here
if ((*env)->ExceptionCheck(env))
return;
还有 Java class 很好的衡量标准:
public final class MclassInfo {
private native void _get(final Kvdb kvdb, Mclass mclass) throws HseException;
private long allocatedBytes;
private long usedBytes;
private Path path;
MclassInfo(final Kvdb kvdb, final Mclass mclass) throws HseException {
_get(kvdb, mclass);
}
public long getAllocatedBytes() {
return allocatedBytes;
}
public long getUsedBytes() {
return usedBytes;
}
public Path getPath() {
return path;
}
}
我能想到的就是我没有正确调用 Java 可变参数函数。我也尝试将 NULL
作为额外参数传递给方法调用,但最终遇到了同样的问题。
您尝试调用的方法声明为 get(String first, String... more)
。 Java 中的可变参数语法只是指定类型数组的糖,即此方法的 两个 参数实际上是 String
和 String[]
-- 您在 GetStaticMethodID
调用中正确编码为 (Ljava/lang/String;[Ljava/lang/String;)
.
所以要调用它你需要两个参数:一个String
和一个String[]
(数组) -- 并且(对于您的情况)数组必须包含零个元素,但是这样的空数组 not 与 NULL 相同。看看 NewObjectArray
.
我目前正在为我使用的 C 库创建一些 Java 绑定。我们的一个 C 结构有一个字符缓冲区,它是一个文件系统路径。调用 C 函数后,缓冲区被正确填充。我想获取缓冲区并将其转换为 Java 对象上的 java.nio.file.Path
成员。
不过我遇到了一些麻烦。我出于某种原因在 C 中生成了一个 NullPointerException
,但我看不出问题所在。
创建 java.nio.file.Path
对象的方法是通过 java.nio.file.Paths::get()
。
这里是相关的C代码:
const jclass paths_class = (*env)->FindClass(env, "java/nio/file/Paths");
if ((*env)->ExceptionCheck(env))
return;
const jmethodID get_method = (*env)->GetStaticMethodID(
env, paths_class, "get", "(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;");
if ((*env)->ExceptionCheck(env))
return;
const jstring path_str = (*env)->NewStringUTF(env, info.mi_path);
if ((*env)->ExceptionCheck(env))
return;
const jobject path_obj =
(*env)->CallStaticObjectMethod(env, paths_class, get_method, path_str); // exception generated here
if ((*env)->ExceptionCheck(env))
return;
还有 Java class 很好的衡量标准:
public final class MclassInfo {
private native void _get(final Kvdb kvdb, Mclass mclass) throws HseException;
private long allocatedBytes;
private long usedBytes;
private Path path;
MclassInfo(final Kvdb kvdb, final Mclass mclass) throws HseException {
_get(kvdb, mclass);
}
public long getAllocatedBytes() {
return allocatedBytes;
}
public long getUsedBytes() {
return usedBytes;
}
public Path getPath() {
return path;
}
}
我能想到的就是我没有正确调用 Java 可变参数函数。我也尝试将 NULL
作为额外参数传递给方法调用,但最终遇到了同样的问题。
您尝试调用的方法声明为 get(String first, String... more)
。 Java 中的可变参数语法只是指定类型数组的糖,即此方法的 两个 参数实际上是 String
和 String[]
-- 您在 GetStaticMethodID
调用中正确编码为 (Ljava/lang/String;[Ljava/lang/String;)
.
所以要调用它你需要两个参数:一个String
和一个String[]
(数组) -- 并且(对于您的情况)数组必须包含零个元素,但是这样的空数组 not 与 NULL 相同。看看 NewObjectArray
.