C / C ++ Reflection和JNI – 一种调用尚未编写的本机代码的方法

我正在实现一个Java软件,希望允许C库作为插件。 为了调用这些未来的函数,我需要以某种方式在Java中创建一个本机函数,我可以从中调用尚不存在的代码。 方法签名将是静态的,但方法和类名称可能会更改。

有没有办法检查加载的库或可用的function? 我希望它的工作方式如下:

在我的Java类中,我会有一个函数;

public static native void thirdParty(String class, String method, int[] data, int[] params); 

哪个会在我的C库中调用一个函数;

 JNIEXPORT void JNICALL Java_com_ex_app_Native_thirdParty(JNIEnv *, jclass, jstring, jstring, jintArray, jintArray); 

我可以从中获取类和方法名称,如果它们存在则调用它们,如果它们不存在则抛出exception。

我想我正在寻找的是某种Java风格的reflection,但是在C语言中或者在C ++中失败了。

我怎样才能做到这一点?

标准方式(或通用,因为没有真正的标准)

是创建一个DLL(共享库)。
该DLL具有带有固定名称的“C”函数,该函数返回指向工厂对象的指针。
然后,您可以使用工厂来构建对象。

例:

 DLL-> Wdigets1.dll C function -> extern "C" Fac& getWidgetFactory(); DLL-> BoilerWidget.dll C function -> extern "C" Fac& getWidgetFactory(); DLL-> RoundWidget.dll C function -> extern "C" Fac& getWidgetFactory(); 

因此无论你加载什么dll,你需要做的就是获得一个指向函数getWidgetFactory()的指针,现在你可以使用工厂来构建适当的小部件。

这背后的原因:
允许您动态加载库的库还允许您按名称查找方法/函数。 但您需要使用的名称是全名。 在“C”中,这是明确定义的。 在“C ++”中,这是一个管理的名称,因编译器/平台等而异。因此,可移植代码只能找到“C”名称。

C和C ++并不真正具有Java风格的reflection(尽管有时您可以通过在共享库中查找符号来玩弄技巧)。

更典型的方法是在Java中创建插件接口。 然后,对于每个外部库,您编写一个(希望)少量的自定义Java和/或JNI代码,以将插件接口调用转换为对后端库的调用。

这听起来很像JNA ,它基本上允许您从Java查找和调用本机函数,而无需编写自定义JNI代码。 它使用libffi外部函数库。

方法签名将是静态的,但方法和类名称可能会更改。

在C ++中,方法名称和类名称决定了您正在调用的函数,并用于创建JNI查找的符号(这称为名称修改 )。

还有希望。 我熟悉的插件系统要求每个插件实现一个具有特定名称和签名的C函数(在C ++中,您必须将此函数标记为extern "C" ),这将调用所需的任何其他函数和库,以及插件系统跟踪哪些DLL(Windows)/ SO(UNIX)属于哪个插件,并从相应的文件中调用magic函数。

由于JNI需要文件和函数名称,因此这是实现插件系统的简单方法。