2012-11-09 68 views
2

我已經通過stackoverflow和在互聯網上搜索過,還沒有找到答案。從Java調用C++函數。映射「常量字符*」

我有一個指紋識別器的SDK,我沒有得到源代碼,這意味着我不能改變它。

它有幾個方法,我需要訪問,其界面我會在下面列出(從RS_API.h):

REALSCANSDK_API int __stdcall RS_InitSDK(const char* configFileName, int option, int* numOfDevice); 
REALSCANSDK_API int __stdcall RS_InitDevice(int deviceIndex, int*deviceHandle); 
REALSCANSDK_API int __stdcall RS_SetCaptureMode(int deviceHandle, int captureMode, int captureOption, bool withModeLED); 
REALSCANSDK_API int __stdcall RS_SetViewWindow(int deviceHandle, HWND windowHandle, RECT drawRectangle, bool autoContrast); 
REALSCANSDK_API int __stdcall RS_TakeImageDataEx(int deviceHandle, int timeout, int fingerIndex, bool withLED, unsigned char** imageData, int* imageWidth, int* imageHeight); 

我設法他們都轉換爲德爾福,但我也想訪問它來自一個Java應用程序。

我的原型是這樣的:

public class Leitor { 
    public native int RS_InitSDK(String configFileName, int option, int numOfDevice); 

    public static void main(String[] args) { 
     Leitor leitor= new Leitor(); 
     leitor.RS_InitSDK(null, 0, 0); 
    } 
    static 
    { 
    System.load("C:\\temp\\SDKSuprema\\SDK\\RS_SDK.dll");  
    } 
} 

負載位工作正常(我相信這意味着它可以查找DLL文件),但是當它運行的本地方法就拋出異常:

線程「main」中的異常java.lang.UnsatisfiedLinkError:leitor.Leitor.RS_InitSDK(Ljava/lang/String; II)I at leitor.Leitor.RS_InitSK(Native Method) at leitor.Leitor.main(Leitor。 java:14)

I f我重命名DLL它將錯誤更改爲「無法加載庫」,所以我認爲問題在於這些方法的映射。

我也找不到如何映射通過引用參數傳遞從Java調用。唯一的解決方案是通過改變DLL來返回一個結構,而不是一個單一的結果,但這是不可能的,因爲我不能改變代碼。

的第二個問題將是從SWT的JNI本地方法發送的窗口句柄...

任何幫助是極大的歡迎!

+0

看起來您正在尋找的是[JavaCPP](http://code.google.com/p/javacpp/)或我在該頁上列出的其他工具之一。 –

回答

2

您需要編寫顯式粘合代碼,它接受參數作爲Java對象並將它們轉換爲現有C入口點期望的表示形式。 JVM本身不會爲你做這件事。

閱讀JNI specification瞭解如何編寫此膠水代碼。

特別是,爲了匹配您的Java聲明,JNI入口點必須命名爲package_name_here_Leitor_RS_1InitSDKpackage_name_here_Leitor_RS_1InitSDK__Ljava_lang_String_2II;請參閱「解析本地方法名稱」規範第2章的一節。這個函數必須在Java可見的前面添加一些額外的參數;在規範中參見「本地方法參數」

在該方法中,您將字符串作爲jstring值傳遞,您必須使用JVM中的GetStringUTFChars輔助函數將其轉換爲C字符串。

對於傳遞引用參數,您需要找到一種方法來模擬它們,這對調用Java代碼有意義,比如通過傳遞一個由JNI代碼分配字段的對象,或者通過一個int[],其第一個元素由您的JNI代碼分配。

+0

從Java調用它們時,我總是將C++庫封裝在自己的粘膠類中。它將你從古怪的行爲中隔離出來,並讓你完全控制只暴露你需要使用的部分。 – Kieveli

1

您需要創建c/C++ glue代碼來實現java方法,用類調用javah將創建一個頭,並將java方法的原生對象標記爲native。

如果您不想編寫c/C++,則可以使用JNA在大多數情況下將java代碼映射到現有的c方法和結構。