1

我正在实现一个 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++ 中失败。

我怎样才能做到这一点?

4

4 回答 4

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”名称。

于 2009-06-06T00:12:12.787 回答
2

C 和 C++ 并没有真正的 Java 风格的反射(尽管有时您可以通过在共享库中查找符号来耍花招)。

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

于 2009-06-05T22:44:34.260 回答
1

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

于 2009-06-06T02:04:08.927 回答
0

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

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

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

由于 JNI 需要一个文件和一个函数名,因此这是实现插件系统的一种直接方式。

于 2009-06-05T23:48:57.000 回答