我打算编写一个Java FFI库,它将使用DynASM在运行时生成FFI trampolines,而不是通过libffi执行解释调用。
至少在最初,我不打算按值支持传递/返回复合类型。将通过直接ByteBuffer
在Java中创建C数据结构。指针将通过sun.misc.Unsafe
获取并解除引用,并表示为Java long
值。
JNI呼叫的工作原理如下:
JNIEXPORT t JNICALL my_c_func(JNIEnv *env, jobject *self, jlong arg);
问题在于有两个不需要的参数。我想写一个删除这两个参数然后调用实际函数的trampoline。在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程序执行此操作,但我知道在许可许可下没有实现。
答案 0 :(得分:0)
我会回答两个不同的事情,因为我不确定你在问什么,我不知道你是否在询问:
所以我会给你两个回答:
我认为您认为JNIEnv *env, jobject *self
是两个不需要的参数,但它们是必需的。这些参数对您来说是透明的,因为它们由JNI管理。
让我解释一下。从Java,您想要调用本机函数,例如:
private static native void myFunc(String param1);
为了在Java和本机C / C ++代码之间建立桥梁,您需要调用其签名将为
的本机funtcionJNIEXPORT void JNICALL Java_MyClass_myFunc(JNIEnv *, jclass, jstring);
如您所见,有两个参数JNIEnv *
和jclass
由JNI管理,但您的本机函数只有一个String
参数,映射到第三个{{ 1}} JNI原生呼叫。
如果您尝试从C / C ++代码的其他部分调用此函数,那么您错了,因为您不能。必须从JNI调用此函数,才能正确传递对JNI Environment的引用并为调用对象提供自引用。
如果你想这样做,那么你将不得不创建另一个函数,独立于可以从JNI函数和其他C / C ++函数调用的JNI。
这样你就可以将逻辑与视图分离,考虑到JNI调用一个可以访问逻辑的视图。
希望它有所帮助。