2011-08-05 30 views
1

我有一個.cpp和.h文件的C++項目。其中一個.cpp具有此簽名的功能:

int** verts(int L, int W, int l, int w)

我想在Java項目中使用此函數。是的,我可以用Java重寫它,但它是一個非常明確的函數。從Java調用這個函數(並獲得一個整數矩陣)將會很棒。

有什麼想法?
請認爲我是一名Java程序員,我很喜歡C++:P在Java中使用C++函數

+1

jni有很多例子。這裏有一個http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jni.html –

回答

2

你可以編寫一個包含這個函數的庫,並用 包裝一個JNI包裝器,但它不是微不足道的。最重要的問題是 int**究竟代表什麼,以及如何管理它們:是否和 如何刪除它們以及如何在Java中表示它們。 只是猜測,我懷疑這個指針指向的數組是int*, 每個指向一個數組int;這是C中二維數組的一種常見的 表示(但不是我們通常在C++中使用的 )。至於是否以及如何刪除它們,這個 應該由定義爲verts的庫記錄。鑑於此, 你首先必須聲明該函數作爲本地Java類:

class Verts 
{ 
    static { 
     System.loadLibrary("<i>libraryName</i>"); 
    } 

    private static Integer[] nativeVerts(int L, int W, int l, int w); 
    public Integer[][] verts(int L, int W, int l, int w) 
    { 
     Integer[] tmp = nativeVerts(L, W, l, w); 
     // reshape tmp... 
     return reshapedData; 
    } 
} 

(我主張回到扁平,一維數組,而 不是Integer[][]它將使且該C++簡單得多)

什麼你需要做的就是寫大意如下的功能:

#include "jni.h" 
extern "C" JNIEXPORT jIntArray JNICALL Java_Verts_nativeVerts(
    JNIEnv* env, 
    jclass, 
    jint L, 
    jint W, 
    jint l, 
    jint w) 
{ 
    int** results = verts(L, W, l, w); 
    std::vector<int> tmp; 
    // Fill tmp with the flattened results. 
    // Then do whatever you have to do to clean up the int**. 
    jintArray jResults = env->newIntArray(tmp.size()); 
    env->SetIntArrayRegion(jResults, 0, tmp.size(), &tmp[0]); 
    return jResults; 
} 

除了以上還需要相當多的錯誤檢查。

最後,將上面的代碼編譯並鏈接到一個dll中,並在Java端爲您提供的名稱爲 System.loadLibrary()函數。並確保您的環境已設置,以便Java可以通過 $ LD_LIBRARY_PATH(Unix)或%path%(Windows)或通過在Java命令行上傳遞 方式的-Djava.library.path=...來找到dll。

+0

非常感謝您的回答。我想嘗試,但我得到這個錯誤,當我加載DLL ...「java.lang.UnsatisfiedLinkError:無法加載IA 32位.dll在AMD 64位平臺上」 – Oneiros

+0

我在Windows 7 64位,但我使用的是32位版本的jdk – Oneiros

+0

@Oneiros然後,您必須將DLL鏈接爲32位DLL。(我無法幫到你 - 我的Windows機器都運行Windows的32位版本。) –

1

您將無法直接使用該函數(或者如果您這樣做,您將會發生內存泄漏,因爲Java不知道如何釋放由verts分配並返回的內存)。你應該可以編寫一個遵循JNI規則的簡單包裝器。

當跨語言進行調用時,您確實需要使用調用方提供的緩衝區。對於此函數,包裝器需要將結果複製到調用方提供的緩衝區,然後使用相應的C++函數釋放由verts返回的內存。