gpt4 book ai didi

C# 平台调用,具有引用和值类型的 C 风格 union

转载 作者:太空宇宙 更新时间:2023-11-04 01:37:56 25 4
gpt4 key购买 nike

我正在尝试整理以下结构

struct OpalMessage {
OpalMessageType m_type; ///< Type of message
union {
const char * m_commandError; ///< Used by OpalIndCommandError
OpalParamGeneral m_general; ///< Used by OpalCmdSetGeneralParameters
OpalParamProtocol m_protocol; ///< Used by OpalCmdSetProtocolParameters
OpalParamRegistration m_registrationInfo; ///< Used by OpalCmdRegistration
OpalStatusRegistration m_registrationStatus; ///< Used by OpalIndRegistration
OpalParamSetUpCall m_callSetUp; ///< Used by OpalCmdSetUpCall/OpalIndProceeding/OpalIndAlerting/OpalIndEstablished
const char * m_callToken; ///< Used by OpalCmdHoldcall/OpalCmdRetrieveCall/OpalCmdStopRecording
OpalStatusIncomingCall m_incomingCall; ///< Used by OpalIndIncomingCall
OpalParamAnswerCall m_answerCall; ///< Used by OpalCmdAnswerCall/OpalCmdAlerting
OpalStatusUserInput m_userInput; ///< Used by OpalIndUserInput/OpalCmdUserInput
OpalStatusMessageWaiting m_messageWaiting; ///< Used by OpalIndMessageWaiting
OpalStatusLineAppearance m_lineAppearance; ///< Used by OpalIndLineAppearance
OpalStatusCallCleared m_callCleared; ///< Used by OpalIndCallCleared
OpalParamCallCleared m_clearCall; ///< Used by OpalCmdClearCall
OpalStatusMediaStream m_mediaStream; ///< Used by OpalIndMediaStream/OpalCmdMediaStream
OpalParamSetUserData m_setUserData; ///< Used by OpalCmdSetUserData
OpalParamRecording m_recording; ///< Used by OpalCmdStartRecording
OpalStatusTransferCall m_transferStatus; ///< Used by OpalIndTransferCall
OpalStatusIVR m_ivrStatus; ///< Used by OpalIndCompletedIVR
} m_param;
};

转到 C#。明显的问题是这两个字符串不可避免地是引用类型。

所以,我尝试了这个:

    [StructLayout(LayoutKind.Explicit)]
public struct OpalMessageStrUnion
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.LPStr)]
public string m_commandError; ///< Used by OpalIndCommandError

[FieldOffset(0)]
[MarshalAs(UnmanagedType.LPStr)]
public string m_callToken; ///< Used by OpalCmdHoldcall/OpalCmdRetrieveCall/OpalCmdStopRecording
}

[StructLayout(LayoutKind.Explicit)]
public struct OpalMessageUnion
{
[FieldOffset(0)]
public OpalParamGeneral m_general; ///< Used by OpalCmdSetGeneralParameters

[FieldOffset(0)]
public OpalParamProtocol m_protocol; ///< Used by OpalCmdSetProtocolParameters

[FieldOffset(0)]
public OpalParamRegistration m_registrationInfo; ///< Used by OpalCmdRegistration

[FieldOffset(0)]
public OpalStatusRegistration m_registrationStatus; ///< Used by OpalIndRegistration

[FieldOffset(0)]
public OpalParamSetUpCall m_callSetUp; ///< Used by OpalCmdSetUpCall/OpalIndProceeding/OpalIndAlerting/OpalIndEstablished

[FieldOffset(0)]
public OpalStatusIncomingCall m_incomingCall; ///< Used by OpalIndIncomingCall

[FieldOffset(0)]
public OpalParamAnswerCall m_answerCall; ///< Used by OpalCmdAnswerCall/OpalCmdAlerting

[FieldOffset(0)]
public OpalStatusUserInput m_userInput; ///< Used by OpalIndUserInput/OpalCmdUserInput

[FieldOffset(0)]
public OpalStatusMessageWaiting m_messageWaiting; ///< Used by OpalIndMessageWaiting

[FieldOffset(0)]
public OpalStatusLineAppearance m_lineAppearance; ///< Used by OpalIndLineAppearance

[FieldOffset(0)]
public OpalStatusCallCleared m_callCleared; ///< Used by OpalIndCallCleared

[FieldOffset(0)]
public OpalParamCallCleared m_clearCall; ///< Used by OpalCmdClearCall

[FieldOffset(0)]
public OpalStatusMediaStream m_mediaStream; ///< Used by OpalIndMediaStream/OpalCmdMediaStream

[FieldOffset(0)]
public OpalParamSetUserData m_setUserData; ///< Used by OpalCmdSetUserData

[FieldOffset(0)]
public OpalParamRecording m_recording; ///< Used by OpalCmdStartRecording

[FieldOffset(0)]
public OpalStatusTransferCall m_transferStatus; ///< Used by OpalIndTransferCall

[FieldOffset(0)]
public OpalStatusIVR m_ivrStatus; ///< Used by OpalIndCompletedIVR

}

/// <summary>
/// Message to/from OPAL system.
/// This is passed via the OpalGetMessage() or OpalSendMessage() functions.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct OpalMessage
{
//this guy is an enumeration b.t.w.
/// <summary>
/// type of message
/// </summary>
[FieldOffset(0)]
public OpalMessageType m_type;

[FieldOffset(4)]
public OpalMessageUnion m_param;

[FieldOffset(4)]
public OpalMessageStrUnion m_strParam;
}

但是,我仍然收到编码错误,告诉我这行不通,因为我在同一内存位置混合了一个对象和非对象类型。我现在假设结构本身(即 OpalParamGeneral 等)也不能混合引用和值类型,即使它们是按顺序排列的?

顺便说一下,对每个结构进行单独的函数调用不是一种选择。我宁愿写一个 COM 包装器也不愿那样做。

最佳答案

[StructLayout(LayoutKind.Explicit)] 属性是不寻常的,它不仅在编码(marshal)时影响结构的布局,而且还影响结构的托管版本的布局。这可能非常方便,它允许在托管语言中实现 union ,即使该语言本身不支持 union 。

它们会带来麻烦,但是垃圾收集器对它们有问题。它需要能够找到对引用类型的引用,但在 union 中不能可靠地做到这一点。因为它无法准确判断引用的是什么类型。这也是一个可靠性问题,您可以将引用类型与 IntPtr 重叠,并以这种方式发现对象的地址。

CLR 类加载器检查此条件并在发生重叠时抛出 TypeLoadException。

解决方法很明确,您需要确保只使用 blittable 类型。您的所有 OpalXxx 类型都需要是本身仅包含可 blittable 类型的结构。字符串的解决方法是改为将它们声明为 IntPtr 并使用 Marshal 类来转换值。在此 MSDN library article 中更多关于 blittable 类型的信息.

关于C# 平台调用,具有引用和值类型的 C 风格 union ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11285984/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com