簡體   English   中英

我可以使用JNI在Java代碼中引用C ++對象嗎?

[英]Can I reference C++ objects in Java Code using JNI?

我沒有在任何地方看到這個(或者我可能很簡單沒有看到它)但有沒有辦法使用JNI返回c / c ++對象並在java中使用該對象?

例如(非常簡單):

class simpleClass{
...
private:
int intVar;
public:
int getIntVar();
void setIntVar(int someNum);
...
}

在我的java代碼中,我將如何執行以下操作:

...
simpleClass sc = new simpleClass();
sc.setIntVar(9);
System.out.println(sc.getIntVar());
...

我意識到這是一個非常簡單的例子,但我只是在尋找概念 - 我在c ++中考慮的類是非常大的,我希望避免創建一個TON的包裝器方法......

如果它不可能那么好,只是希望節省幾天編碼大聲笑

您的Java版SimpleClass應該做兩件事。 一,保留一個私有long值,將C ++指針的值存儲到后備本機對象(您可能必須使用BigInteger,具體取決於本機指針的大小 - unsigned long long?)。 二,使公共方法(例如setIntVal )原生。

public class SimpleClass {
    private long nativePtr;

    public SimpleClass() {
        nativePtr = initNativeSimpleClass();
    }

    public void destroy() {
        destroyNativeSimpleClass();
        nativePtr = 0L;
    }

    protected void finalize() throws Throwable {
        destroyNativeSimpleClass();
        nativePtr = 0L;
    }

    public native int getIntVal();
    public native void setIntVal(int val);

    private native long initNativeSimpleClass();
    private native void destroyNativeSimpleClass();
}

然后在JNI代碼中實現這些本機方法。 initNativeSimpleClass()方法將新建一個SimpleClass的支持C ++實例。 然后, destroyNativeSimpleClass()方法將刪除該實例。 訪問器方法將使用nativePtr的值,將其nativePtr轉換為實際指針,並在本機后備實例上執行適當的操作。

這個成語存在泄漏內存的真正風險,因為類的用戶必須在完成實例時調用destroy。 如果不這樣做,則可能無法正確銷毀后備本機實例。 正如我在示例中所示,您可以覆蓋finalize以調用本機驅逐程序函數,但是關於如何無法依賴finalize的所有警告仍然適用。 通過在銷毀時將nativePtr值設置為0,如果多次調用destroy,則可以避免seg錯誤(在C ++中刪除NULL是安全的)。

不,你不能。 C ++和Java ABI完全不同 - 例如,c ++沒有定義一個。 實際上,c ++有很多功能無法映射到Java,但這些功能無法正常工作。 您如何期望Java能夠處理c ++模板? 對原始人的指針? 不是指針的對象?

現在你可以做的是,使用SWIG為你生成正確的包裝器方法 - 這實際上可以工作,並且工作量遠遠超過你的計划:)

JNI僅為原始(或相當原始)類型定義其接口,以及內存緩沖區傳遞/管理功能。 無法映射復雜的對象類型。 但是,您可以通過編寫自己的(單個)序列化/反序列化函數來實現此效果,就像通過JNI將C ++類返回到Java一樣

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM