在 C# 中使用非基元数据固定对象

本文关键字:元数据 对象 | 更新日期: 2023-09-27 18:30:40

我有一个与机器的通信接口,并得到了一个dll,提供了许多可以使用的功能。 只要我有沟通,一切都很好。 如果在 5 分钟内没有任何可通信的内容,则功能将不再起作用。 我想这是因为垃圾收集器清理了这一切。 经过一些研究,我可能应该把它固定在GCHandle.Alloc(object, GCHandleType.Pinned);

下面是一些代码:

对象

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DNCC_PARAM
{
    public int nMacNo;
    public int nOwnPort;
    public int nIpAddr;
    public int nNCPort;
    [MarshalAsAttribute(UnmanagedType.FunctionPtr)]
    public Delegate CallBackFunction;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public short[] arrTimeout = new short[20];
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public short[] arrRetry = new short[20];
}

一些 DLL 导入

[DllImport(@"path to dll", CharSet = CharSet.Ansi)]
public static extern int Initialize([In()] DNCC_PARAM dncPara);
[DllImport(@"path to dll", CharSet = CharSet.Ansi)]
private static extern int dncc_Connect(int hdl);
[DllImport(@"path to dll", CharSet = CharSet.Ansi)]
private static extern int dncc_Disconnect(int hdl);

对象的实例

DNCC_PARAM param = new DNCC_PARAM();

初始化通信

// fill the object with some data
param.nMacNo = 1;
param.nOwnPort = 7005;
param.nIpAddr = (int)IPAddress.Parse("192.168.0.10").Address;
param.nNCPort = 7005;
param.CallBackFunction = new TypeOfCallBackFunction(AppCallBack);
// init the communication
nDNCC_HANDLE = Initialize(param);

回调函数

private void AppCallBack(int iHandle, int iEvent, IntPtr arg)
{
    // doing some stuff here
}

因此,当我尝试像这样固定对象时GCHandle.Alloc(param, GCHandleType.Pinned);我会收到一条消息,指出该对象不包含原始数据。 如何防止对象被 GC 清除?

我目前的"解决方案"是一个计时器,它每分钟左右就会进行一些通信。 我工作,但我想相当丑陋。

在 C# 中使用非基元数据固定对象

我想你正在寻找Marshal.StructureToPtr.关键是,您分配的托管对象没有与您尝试通过MarshalAs属性描述的非托管布局相对应的内存布局。因此,您需要 Marshal 类来创建具有所需布局的结构的非托管副本

仅当托管和非托管内存布局相同时,才能使用GCHandle,因此可以使用相同的内存。