我试图将pjsip_event包装到C#中,结构的顶层似乎是正确的但是子部分似乎直接指向未知的内存。
尝试换行的结构:
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的其余部分似乎有正确的值,否则只是随机的东西。
任何想法在这个阶段都会有所帮助
答案 0 :(得分: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;
}