我计划编写一个 Java FFI 库,它将使用 DynASM在运行时生成 FFI 蹦床,而不是通过 libffi 执行解释调用。
至少在最初,我不打算支持按值传递/返回复合类型。 C 数据结构将通过直接的 ByteBuffer 在 Java 中创建。指针将通过 sun.misc.Unsafe
获取和取消引用,并表示为 Java long
值。
JNI 调用的工作原理如下:
JNIEXPORT t JNICALL my_c_func(JNIEnv *env, jobject *self, jlong arg);
问题是有两个不需要的参数。我想编写一个蹦床来删除这两个参数,然后调用实际的函数。在 Windows 系统上,它需要从 stdcall
(由 Windows 上的 JNI 使用)转换为 stdcall
、cdecl
或 thiscall
。另外,DynASM 不支持动态寄存器分配。
问题实际上非常简单:我如何(在汇编中)将一个函数除了前两个参数之外的所有参数传递给另一个函数?在 C 中,我将生成一个函数,如下所示:
jlong my_function(JNIEnv* env, jobject obj, jlong val) {
return called_function(val);
}
我正在尝试在汇编中执行此操作。 objc_msgsend
对 Objective-C 程序执行此操作,但据我所知,在宽松的许可证下没有实现。
最佳答案
我会回答两个不同的问题,因为我不确定你到底在问什么,我不知道你是否在问:
- JNI 函数中的两个额外参数要从 Java 代码调用,或者
- JNI 函数中的两个额外参数可从 C/C++ 代码调用。
所以我给你两个答案:
假设Java调用
我认为您认为 JNIEnv *env, jobject *self
是两个不需要的参数,但它们是必需的。这些参数对您来说是透明的,因为它们是由 JNI 管理的。
让我解释一下。在 Java 中,您想要调用 native 函数,例如:
private static native void myFunc(String param1);
为了在 Java 和 native C/C++ 代码之间建立桥梁,您需要调用一个 native 函数,其签名为
JNIEXPORT void JNICALL Java_MyClass_myFunc(JNIEnv *, jclass, jstring);
如您所见,有两个参数 JNIEnv *
和 jclass
是通过 JNI 管理的,但您的 native 函数只有一个 String
> 映射到第三个 jstring
JNI native 调用的参数。
假设 C/C++ 调用
如果您尝试从 C/C++ 代码的另一部分调用此函数,那么您就错了,因为您不能。该函数必须从 JNI 调用,以便正确传递对 JNI 环境的引用并为调用对象提供自引用。
如果您想这样做,那么您将必须创建另一个独立于 JNI 的函数,该函数可以从 JNI 函数和其他 C/C++ 函数调用。
通过这种方式,您可以将逻辑与 View 解耦,考虑到 JNI 调用可以访问逻辑的 View 。
希望有帮助。
关于java - 将函数的前 2 个参数之外的所有参数传递给另一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32929757/