2009-06-05 26 views
1

我正在實現一款Java軟件,希望允許C庫作爲插件。爲了調用這些將來的函數,我需要以某種方式在Java中創建一個本地函數,從中我可以調用尚不存在的代碼。方法簽名將是靜態的,但方法和類名稱可能會更改。C/C++反射和JNI - 一種調用尚未編寫的本地代碼的方法

有沒有辦法檢查加載的庫或可用函數?我希望它的工作方式如下:

在我的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++。

我該如何做到這一點?

回答

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」名稱。

2

C和C++並沒有真正的Java風格的反射(儘管有時候你可以在共​​享庫中查找符號來玩技巧)。

更典型的方法是在Java中創建插件接口。然後,爲每個外部庫編寫(希望)少量的自定義Java和/或JNI代碼,以將插件接口調用轉換爲對後端庫的調用。

+0

此方法是否需要每個插件的新Java代碼?每個插件都提供了一個具有相同參數但執行不同計算的方法。 安裝後將修復java代碼,我想支持不同的C插件庫。 對不起,如果這是你已經回答的問題,我只是想澄清。 – gav 2009-06-10 14:28:24

0

方法簽名將是靜態的,但方法和類名稱可能會更改。

在C++中的方法名稱和類名是什麼決定你叫什麼功能,以及用於創建符號JNI查找(這就是所謂的name mangling)。

有希望。 plugin systems I'm familiar with要求每個插件實現具有特定名稱和簽名的C函數(在C++中,您必須將此函數標記爲extern "C"),這將調用所需的任何其他函數和庫,並且插件系統會跟蹤哪些DLL(Windows)/SO(UNIX)屬於哪個插件,並從相應的文件調用魔術功能。

由於JNI需要一個文件和一個函數名,所以這是實現插件系統的直接方式。

1

這聽起來很像JNA,它基本上允許您在不編寫自定義JNI代碼的情況下查找並調用Java的本地函數。它使用libffi外部函數庫。