将函数的前2个参数传递给另一个函数

时间:2015-10-04 03:31:09

标签: java c jit ffi calling-convention

我打算编写一个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使用)转换为stdcallcdeclthiscall。此外,DynASM不支持动态寄存器分配。

问题其实很简单:我如何(在汇编中)将除函数的前两个参数之外的所有参数传递给另一个函数?在C中,我将生成如下函数:

jlong my_function(JNIEnv* env, jobject obj, jlong val) {
   return called_function(val);
}

我想在集会中这样做。 objc_msgsend为Objective-C程序执行此操作,但我知道在许可许可下没有实现。

1 个答案:

答案 0 :(得分:0)

我会回答两个不同的事情,因为我不确定你在问什么,我不知道你是否在询问:

  • 从Java代码调用JNI函数中的两个额外参数,或
  • 从C / C ++代码调用JNI函数中的两个额外参数。

所以我会给你两个回答:

假设Java调用

我认为您认为JNIEnv *env, jobject *self是两个不需要的参数,但它们是必需的。这些参数对您来说是透明的,因为它们由JNI管理。

让我解释一下。从Java,您想要调用本机函数,例如:

private static native void myFunc(String param1);

为了在Java和本机C / C ++代码之间建立桥梁,您需要调用其签名将为

的本机funtcion
JNIEXPORT void JNICALL Java_MyClass_myFunc(JNIEnv *, jclass, jstring);

如您所见,有两个参数JNIEnv *jclass由JNI管理,但您的本机函数只有一个String参数,映射到第三个{{ 1}} JNI原生呼叫。

假设C / C ++调用

如果您尝试从C / C ++代码的其他部分调用此函数,那么您错了,因为您不能。必须从JNI调用此函数,才能正确传递对JNI Environment的引用并为调用对象提供自引用。

如果你想这样做,那么你将不得不创建另一个函数,独立于可以从JNI函数和其他C / C ++函数调用的JNI。

这样你就可以将逻辑与视图分离,考虑到JNI调用一个可以访问逻辑的视图。

希望它有所帮助。