1

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の残りの部分は正しい値を持っているようですが、それ以外の場合は単なるランダムなものです。

この段階では、どんなアイデアでも役に立ちます

4

1 に答える 1

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;
}
于 2013-11-15T23:51:45.340 に答える