【问题标题】:C# Define custom UnmanagedType for the MarshalAs attribute classC# 为 MarshalAs 属性类定义自定义 UnmanagedType
【发布时间】:2011-11-28 10:22:40
【问题描述】:

是否可以为 MarshalAs 属性类定义自定义 UnmanagedType? 具体来说,我想将 long int unix 时间转换为 DateTime 类型。像这样的:

[MarshalAs(UnmanagedType.LongTimeUnix)]
public DateTime Time;

自定义的LongTimeUnix枚举类型要放在哪里,时间转换码要放在哪里:

public static DateTime ConvertUnix2DateTime(long timeStamp)
{
        DateTime DT = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        DT = DT.AddSeconds(timeStamp);
        return DT;
}

当传输数据时

(SomeStruct)Marshal.PtrToStructure(
 IntPtr,
 typeof(SomeStruct));

我希望用上面的代码sinppet自动转换长时间的unix。 我是否必须从 MarshalAs 类继承并将转换写入此类? 谢谢,于尔根

更新 这是自定义编组器:

class MarshalTest : ICustomMarshaler
{
    public void CleanUpManagedData(object ManagedObj)
    {
        throw new NotImplementedException();
    }

    public void CleanUpNativeData(IntPtr pNativeData)
    {
        throw new NotImplementedException();
    }

    public int GetNativeDataSize()
    {
        return 8;
    }

    public IntPtr MarshalManagedToNative(object ManagedObj)
    {
        throw new NotImplementedException();
    }

    public object MarshalNativeToManaged(IntPtr pNativeData)
    {
        long UnixTime = 0;
        try
        {
            UnixTime = Marshal.ReadInt64(pNativeData);
        }
        catch (Exception e)
        {

           QFXLogger.Error(e, "MarshalNativeToManaged");
        }
        DateTime DT = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        DT = DT.AddSeconds(UnixTime);
        return DT;
    }
 }

这是类定义:

unsafe public struct MT5ServerAttributes
{
    /// <summary>
    /// Last known server time.
    /// </summary>
    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MarshalTest))]
    public DateTime CurrentTime;

    //[MarshalAs(UnmanagedType.U8)]
    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MarshalTest))]
    public DateTime TradeTime;

 }

最后是从非托管内存中编组数据的代码:

try
{
   MT5ServerAttributes MT5SrvAttributes = (MT5ServerAttributes)Marshal.PtrToStructure(mMT5Proxy.MT5InformationProxy.ServerData,
                                                                    typeof(MT5ServerAttributes));
}
catch (Exception e)
{

QFXLogger.Error(e, "ConsumeCommand inner");
}

运行时会抛出以下异常(这不是 PtrToStructure 的直接异常!) 无法封送“QFX_DLL.MT5ServerAttributes”类型的字段“CurrentTime”:托管/非托管类型组合无效(DateTime 类必须与 Struct 配对)。 有什么想法吗?

【问题讨论】:

    标签: c# marshalling unmanaged unix-timestamp


    【解决方案1】:

    您不能将自己的枚举添加到枚举中,但可以使用UnmanagedType.CustomMarshaler。指定您要使用自定义类型对其进行编组。

    MSDN 有一整节专门讨论这个问题。

    你最终会按照这些思路做一些事情:

    [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyCustomMarshaler))]
    public DateTime Time;
    

    然后将 MyCustomMarshaler 实现为 ICustomMarshaler

    【讨论】:

    • 这真的有效吗?我也在尝试同样的方法,但它失败了,因为您不能在班级成员上使用 CustomMarshaler。据我所知CustomMarshaler 仅适用于函数参数(这很痛苦)。
    • 不,@J.N. 我也不高兴。我从他的评论中怀疑@Juergen 在实际尝试之前将其标记为答案。如果您跳过调用Marshal.SizeOf 的步骤并直接转到Marshal.PtrToStructure 调用,您将收到错误“自定义封送器不能用于结构字段。”做不到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2012-02-15
    • 2017-05-31
    相关资源
    最近更新 更多