C# 为 MarshalAs 属性类定义自定义 UnmanagedType

发布于 2024-12-07 09:50:48 字数 2498 浏览 3 评论 0原文

是否可以为 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 配对)。 有什么想法吗?

is it possible to define a custom UnmanagedType for the MarshalAs attribute class?
Specifically I want to convert a long int unix time into a DateTime type. Something like this:

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

Where do I have to put the custom LongTimeUnix enumeration type and where to put the time conversion code:

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

When transferring the data with

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

I want that the long time unix is automatically converted with the code sinppet above.
Do I have to inherit from the MarshalAs class and write the conversion into this class?
Thanks, Juergen

Update
Here is the custom marshaller:

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;
    }
 }

Here is the class definition:

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;

 }

And finally the code to marshal the data from unmanaged memory:

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

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

When running this the following excpetion is thrown(which is not a direct exception ot PtrToStructure!)
Cannot marshal field 'CurrentTime' of type 'QFX_DLL.MT5ServerAttributes': Invalid managed/unmanaged type combination (the DateTime class must be paired with Struct).
Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

复古式 2024-12-14 09:50:48

您无法将自己的枚举添加到枚举中,但可以使用UnmanagementType.CustomMarshaler。指定您要使用自定义类型对其进行封送。

MSDN 有一整节专门介绍这一点。

您最终会按照以下方式做一些事情:

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

然后将 MyCustomMarshaler 实现为 ICustomMarshaler

You cannot add your own to the enumeration, but you can use UnmanagedType.CustomMarshaler. To specify that you want to marshal it using a custom type.

MSDN has an entire section dedicated to this.

You would end up doing something along these lines:

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

Then implement MyCustomMarshaler as ICustomMarshaler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文