2015-11-06 85 views
7

我有以下需要映射到Java的C結構。因爲我需要從C代碼生成的DLL中調用一個方法。以下是我的結構。如何將C Structure的以下元素映射到Java?

typedef struct _ipj_iri_device 
{ 
IPJ_READER_CONTEXT reader_context; 
IPJ_READER_IDENTIFIER reader_identifier; 
uint32_t    receive_timeout_ms; 

/* Internal Only */ 
uint8_t    sync_state; 
bool     wait_for_response; 
uint32_t    frame_length; 
uint32_t    receive_index; 
uint8_t    receive_buffer[IPJ_RECEIVE_BUFFER_SIZE]; 

#if !defined(IRI_RX_ONLY) 
uint8_t    transmit_buffer[IPJ_TRANSMIT_BUFFER_SIZE]; 
#endif 

} ipj_iri_device; 

的IPJ_READER_CONTEXT和IPJ_READER_IDENTIFIER看起來像下面。

typedef void* IPJ_READER_CONTEXT; 
typedef void* IPJ_READER_IDENTIFIER; 

如何解析映射到Java的這兩個元素?請指教。

+0

你不能在java中明確地使用(void)指針。你到一個void *最接近的是使用一個對象作爲類型(並保存在IPJ_READER_CONTEXT和IPJ_READER_IDENTIFIER一個單獨創建對象的相關信息) – ParkerHalo

+0

如果你想從Java調用,這裏的圖書館是一個共享庫函數用C寫的你可能會發現SWIG是你的朋友? – bph

+0

我無法使用swig,因爲我無法編輯現有的C代碼來調整它以符合要求。 – mayooran

回答

-1

啊哈這裏經過一些長期搜索的OOP感興趣的一個VS 功能範例。 所以在這裏我們可以解決它。 這裏是基本步驟。

  • 名稱的結構爲一類。
  • 把結構作爲類屬性的所有屬性。

  • 對於那些無效*,在Java中,你可以使用引用變量。

  • 然後你通過ipj_iri_device的名字給你結構的結構實例,只是在創建一個子彈名爲類的對象。

    public class _ipj_iri_device{ 
        int IPJ_RECEIVE_BUFFER_SIZE ; 
        //get a value from whereever the input is coming ,assign it to buffersize 
        IPJ_READER_CONTEXT reader_context; 
        IPJ_READER_IDENTIFIER reader_identifier; 
        boolean wait_for_response; 
        uint32_t receive_timeout_ms; 
        //here uint32_t is a type i asumed .You will have to define it explicitly 
    
        //rest of the vaariables/members of structure 
    } 
    
+0

如果我創建一個引用變量應該是它的屬性?我應該在引用類內部做什麼?請指教。 – mayooran

+0

IPJ_READER_CONTEXT和IPJ_READER_IDENTIFIER是類型(基本上是一個類),你將不得不根據你的需要來定義它們,但它們的返回類型在你的情況下是無效的。 – shaun

+0

void指針指的是一個內存地址對嗎?所以如果我定義這樣一個班級,我不會在課堂上有任何東西。這是我沒有得到的。這些類包含什麼? – mayooran

0

這裏是你的結構是什麼樣子使用JNA一個例子:

public class ipj_iri_device extends Structure { 
    Pointer    reader_context; 
    Pointer    reader_identifier; 
    int     receive_timeout_ms; 
    /* Internal Only */ 
    byte     sync_state; 
    // field size depends on size of 'bool'; "byte" is usually correct 
    byte     wait_for_response; 
    int     frame_length; 
    int     receive_index; 
    byte[]    receive_buffer = new byte[IPJ_RECEIVE_BUFFER_SIZE]; 
    // may or may not be used, check your native compile flag 
    byte[]    transmit_buffer = new byte[IPJ_TRANSMIT_BUFFER_SIZE]; 
} 

您可以定義備份的reader_contextreader_identifier領域的結構,如果你需要的內容。如果沒有,你可以通過它們作爲一個通用的Pointer

編輯

這些結構可以獨立使用JNA的其餘部分,你需要的是本機內存來移動數據來回的Pointer表示。

+0

我是否需要讓getter和setter來處理結構的元素?這是否像C#結構一樣工作?請指教。 – mayooran

+0

而且我不需要通過Structure.ByReference – mayooran

+0

來實現結構類.JNA默認使用參考語義作爲函數參數,因此不需要顯式的'Structure.ByReference'。 'Structure.read()'和'Structure.write()'處理與本地內存同步字段值,並且在本地函數調用之前和之後由JNA自動調用。 – technomage

0

您可以使用JNIWrapper映射你的C結構,以Java和從DLL調用該函數。

(改變的大小常數需要的值)爲給定的結構將類似於下面顯示的包裝:

import com.jniwrapper.*; 

public class IpjIriDevice extends Structure 
{ 
    private static final int IPJ_RECEIVE_BUFFER_SIZE = 0; 
    private static final int IPJ_TRANSMIT_BUFFER_SIZE = 0; 

    private Pointer.Void reader_context = new Pointer.Void(); 
    private Pointer.Void reader_identifier = new Pointer.Void(); 
    private UInt32 receive_timeout_ms = new UInt32(); 
    private UInt8 sync_state = new UInt8(); 
    private Bool wait_for_response = new Bool(); 
    private UInt32 frame_length = new UInt32(); 
    private UInt32 receive_index = new UInt32(); 
    private PrimitiveArray receive_buffer = new PrimitiveArray(UInt8.class, IPJ_RECEIVE_BUFFER_SIZE); 
    private PrimitiveArray transmit_buffer = new PrimitiveArray(UInt8.class, IPJ_TRANSMIT_BUFFER_SIZE); 

    public IpjIriDevice() 
    { 
     init(new Parameter[] { 
      reader_context, 
      reader_identifier, 
      receive_timeout_ms, 
      sync_state, 
      wait_for_response, 
      frame_length, 
      receive_index, 
      receive_buffer, 
      transmit_buffer 
     }); 
    } 

    public long getReaderContext() 
    { 
     return reader_context.getValue(); 
    } 

    public long getReaderIdentifier() 
    { 
     return reader_identifier.getValue(); 
    } 

    public long getReceiveTimeoutMs() 
    { 
     return receive_timeout_ms.getValue(); 
    } 

    public void setReceiveTimeoutMs(long value) 
    { 
     receive_timeout_ms.setValue(value); 
    } 

    public long getSyncState() 
    { 
     return sync_state.getValue(); 
    } 

    public void setSyncState(long value) 
    { 
     sync_state.setValue(value); 
    } 

    public boolean getWaitForResponse() 
    { 
     return wait_for_response.getValue(); 
    } 

    public void setWaitForResponse(boolean value) 
    { 
     wait_for_response.setValue(value); 
    } 

    public long getFrameLength() 
    { 
     return frame_length.getValue(); 
    } 

    public void setFrameLength(long value) 
    { 
     frame_length.setValue(value); 
    } 

    public long getReceiveIndex() 
    { 
     return receive_index.getValue(); 
    } 

    public void setReceiveIndex(long value) 
    { 
     receive_index.setValue(value); 
    } 

    public PrimitiveArray getReceiveBuffer() 
    { 
     return receive_buffer; 
    } 

    public PrimitiveArray getTransmitBuffer() 
    { 
     return transmit_buffer; 
    } 

    public Object clone() 
    { 
     IpjIriDevice result = new IpjIriDevice(); 
     result.initFrom(this); 
     return result; 
    } 
} 

如果你需要一個指向結構的情況下,你應該創建指針類實例:

IpjIriDevice structureInstance = new IpjIriDevice(); 
Pointer structurePtr = new Pointer(structureInstance); 

之後,您可以使用指針實例傳遞函數參數。下面的代碼演示瞭如何加載庫,並從中調用該函數:

​​

如果結構被調用後修改,所有的改變將在structureInstance對象是可用的。

正如你所看到的,在這種情況下,你不需要寫任何額外的本地代碼。

您可以找到有關其programmer's guide使用JNIWrapper更多細節。此外,還有JNIWrapper forum,其中包含許多常見問題的答案。