我正在实现一个Java软件,希望允许C库作为插件。为了调用这些将来的函数,我需要以某种方式在Java中创建一个本机函数,我可以从中调用尚不存在的代码。方法签名将是静态的,但方法和类名称可能会更改。
有没有办法检查加载的库或可用的函数?我希望它的工作方式如下:
在我的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);
我可以从中获取类和方法名称,如果它们存在则调用它们,如果不存在则抛出异常。
我想我正在寻找的是某种Java风格的反射,但在C语言中或者在C ++中失败。
我怎样才能做到这一点?
答案 0 :(得分:3)
标准方式(或通用,因为没有真正的标准)
是创建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”名称。
答案 1 :(得分:2)
C和C ++实际上没有Java风格的反射(尽管有时候你可以通过在共享库中查找符号来玩弄技巧)。
更典型的方法是在Java中创建插件接口。然后,对于每个外部库,您编写(希望)少量的自定义Java和/或JNI代码,以将插件接口调用转换为对后端库的调用。
答案 2 :(得分:1)
这听起来很像JNA,它基本上允许您在不编写自定义JNI代码的情况下从Java查找和调用本机函数。它使用libffi外部函数库。
答案 3 :(得分:0)
方法签名将是静态的,但方法和类名称可能会更改。
在C ++中,方法名和类名决定了你正在调用的函数,并用于创建JNI寻找的符号(这称为name mangling)。
有希望。 plugin systems I'm familiar with要求每个插件实现具有特定名称和签名的C函数(在C ++中,您必须将此函数标记为extern "C"
),这将调用所需的任何其他函数和库,以及插件系统跟踪哪些DLL(Windows)/ SO(UNIX)属于哪个插件,并从相应的文件中调用magic函数。
由于JNI需要文件和函数名称,因此这是实现插件系统的简单方法。