2013-11-15 20 views
1

我試圖將pjsip_event包裝到C#,結構的頂層似乎是正確的,但子部分似乎直接指向未知內存。P /調用多個級別的聯合

的結構IM試圖總結:

struct pjsip_event 
{ 
/** This is necessary so that we can put events as a list. */ 
PJ_DECL_LIST_MEMBER(struct pjsip_event); 

/** The event type, can be any value of \b pjsip_event_id_e. 
*/ 
pjsip_event_id_e type; //ENUM 

/** 
* The event body as union, which fields depends on the event type. 
* By convention, the first member of each struct in the union must be 
* the pointer which is relevant to the event. 
*/ 
union 
{ 
    /** Timer event. */ 
    struct 
    { 
     pj_timer_entry *entry;  /**< The timer entry.   */ 
    } timer; 

    /** Transaction state has changed event. */ 
    struct 
    { 
     union 
     { 
      pjsip_rx_data *rdata; /**< The incoming message.  */ 
      pjsip_tx_data *tdata; /**< The outgoing message.  */ 
      pj_timer_entry *timer; /**< The timer.     */ 
      pj_status_t  status;/**< Transport error status. */ 
      void   *data; /**< Generic data.    */ 
     } src; 
     pjsip_transaction *tsx; /**< The transaction.   */ 
      int        prev_state; /**< Previous state. */ 
     pjsip_event_id_e  type; /**< Type of event source:  
            *  - PJSIP_EVENT_TX_MSG 
            *  - PJSIP_EVENT_RX_MSG, 
            *  - PJSIP_EVENT_TRANSPORT_ERROR 
            *  - PJSIP_EVENT_TIMER 
            *  - PJSIP_EVENT_USER 
            */ 
    } tsx_state; 

    /** Message transmission event. */ 
    struct 
    { 
     pjsip_tx_data  *tdata; /**< The transmit data buffer. */ 

    } tx_msg; 

    /** Transmission error event. */ 
    struct 
    { 
     pjsip_tx_data  *tdata; /**< The transmit data.   */ 
     pjsip_transaction *tsx; /**< The transaction.   */ 
    } tx_error; 

    /** Message arrival event. */ 
    struct 
    { 
     pjsip_rx_data  *rdata; /**< The receive data buffer. */ 
    } rx_msg; 

    /** User event. */ 
    struct 
    { 
     void    *user1; /**< User data 1.    */ 
     void    *user2; /**< User data 2.    */ 
     void    *user3; /**< User data 3.    */ 
     void    *user4; /**< User data 4.    */ 
    } user; 

} body; 
}; 

#define PJ_DECL_LIST_MEMBER(type)      \ 
            /** List @a prev. */ \ 
            type *prev;   \ 
            /** List @a next. */ \ 
            type *next 

我託管的C#結構是這樣的:

using System; 
using System.Runtime.InteropServices; 

namespace Interop.Enum { 
    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event { 
     public IntPtr prev; 
     public IntPtr next; 

     public pjsip_event_id_e type; //ENUM 

     public pjsip_event__body body; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body { 
     public pjsip_event__body__timer timer; 

     public pjsip_event__body__tsx_state tsx_state; 
     public pjsip_event__body__tx_msg tx_msg; 
     public pjsip_event__body__tx_error tx_error; 
     public pjsip_event__body__rx_msg rx_msg; 
     public pjsip_event__body__user user; 

    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body__timer { 
     public IntPtr entry; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body__tsx_state { 
     public pjsip_event__body__tsx_state__src src; 
     public IntPtr tsx; 
     public int prev_state; 
     public pjsip_event_id_e type; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body__tsx_state__src { 
     public IntPtr rdata; 
     public IntPtr tdata; 
     public IntPtr timer; 
     public int status; 
     public IntPtr data; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body__tx_msg { 
     public IntPtr tdata; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body__tx_error { 
     public IntPtr tdata; 
     public IntPtr tsx; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body__rx_msg { 
     public IntPtr rdata; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct pjsip_event__body__user { 
     public IntPtr user1; 
     public IntPtr user2; 
     public IntPtr user3; 
     public IntPtr user4; 
    } 
} 

我叫下面的方法,來獲得一個指向這個結構:

[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
unsafe public delegate void pjsua_callback_on_call_state(int call_id, pjsip_event* evnt); 

如果我刪除

public pjsip_event__body__tsx_state__src src; 

其餘的pjsip_event_ body _tsx_state__src似乎有正確的值,否則只是隨機的東西。

任何想法在這一階段都將有所幫助

+1

研究聯盟在C/C++中的含義。工會不是結構相同,他們不會轉換成結構... – elgonzo

+1

@elgonzo C#支持結構中的聯盟[此問題和答案](http://social.msdn.microsoft.com/Forums/en-US/60150e7b-665a-49a2-8e2e-2097986142f3/c-equivalent-to-c-union?forum = csharplanguage)上的MSDN fourms。你需要使用'[StructLayout(LayoutKind.Explicit)]'並且聯合點中的每個元素在相同的偏移量 –

+0

@Scott處,感謝鏈接。它看起來很不錯,但也很棒:) – elgonzo

回答

2

工會將每個成員覆蓋在同一內存位置。在C#中,您需要使用LayoutKind.Explicit,併爲每個成員指定FieldOffset零。例如:

[StructLayout(LayoutKind.Explicit)] 
public struct pjsip_event__body__tsx_state__src { 
    [FieldOffset(0)] 
    public IntPtr rdata; 
    [FieldOffset(0)] 
    public IntPtr tdata; 
    [FieldOffset(0)] 
    public IntPtr timer; 
    [FieldOffset(0)] 
    public int status; 
    [FieldOffset(0)] 
    public IntPtr data; 
}