如何分配内存结构,在C#中的数组 [英] How to allocate memory for an array of structure in C#

查看:234
本文介绍了如何分配内存结构,在C#中的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

结构1:

  typedef结构_wfs_cdm_cu_info
{
    USHORT usTellerID;
    USHORT usCount;
    LPWFSCDMCASHUNIT * lppList;
} WFSCDMCUINFO,* LPWFSCDMCUINFO;

2的结构:

typedef结构_wfs_cdm_cashunit
{
    USHORT usNumber;
    USHORT usType;
    LPSTR lpszCashUnitName;
    CHAR cUnitID [5];
    CHAR cCurrencyID [3];
    ULONG ulValues​​;
    ULONG ulInitialCount;
    ULONG ulCount;
    ULONG ulRejectCount;
    ULONG ulMinimum;
    ULONG ulMaximum;
    BOOL bAppLock;
    USHORT usStatus;
    USHORT usNumPhysicalCUs;
    LPWFSCDMPHCU * lppPhysical;
} WFSCDMCASHUNIT,* LPWFSCDMCASHUNIT;

结构3:

typedef结构_wfs_cdm_physicalcu
{
    LPSTR lpPhysicalPositionName;
    CHAR cUnitID [5];
    ULONG ulInitialCount;
    ULONG ulCount;
    ULONG ulRejectCount;
    ULONG ulMaximum;
    USHORT usPStatus;
    BOOL bHardwareSensor;
} WFSCDMPHCU,* LPWFSCDMPHCU;


C#结构: -

<$p$p><$c$c>[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential,字符集= System.Runtime.InteropServices.CharSet.Ansi,包= 1)]
公共结构WFSCDMPHCU { [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
 公共字符串lpPhysicalPositionName;[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 5)]
 公共字符串cUnitID;
 公共UINT ulInitialCount;
 公共UINT ulCount;
 公共UINT ulRejectCount;
 公共UINT ulMaximum;
 公共USHORT usPStatus;
 公众诠释bHardwareSensor;
}


<$p$p><$c$c>[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential,字符集= System.Runtime.InteropServices.CharSet.Ansi,包= 1)]
    公共结构WFSCDMCASHUNIT {
     公共USHORT usNumber;
     公共USHORT usType; [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
     公共字符串lpszCashUnitName;[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 5)]
     公共字符串cUnitID; [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 3)]
     公共字符串cCurrencyID;
     公共UINT ulValues​​;
     公共UINT ulInitialCount;
     公共UINT ulCount;
     公共UINT ulRejectCount;
     公共UINT ulMinimum;
     公共UINT ulMaximum;
     公众诠释bAppLock;
     公共USHORT usStatus;
     公共USHORT usNumPhysicalCUs;
     公共System.IntPtr lppPhysical;
    }


<$p$p><$c$c>[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential,包= 1)]
公共结构WFSCDMCUINFO {
 公共USHORT usTellerID;
 公共USHORT usCount;
 公共System.IntPtr lppList;
}

的DllImport

 函数[DllImport(@Dispenser.dll)]
公共静态外部INT CDM_SetCashUnit(出WFSCDMCUINFO cuinfo);

1)我的主要问题是我应该怎样马歇尔或该结构从C#数据发送到C ++,结构的第二和第三个结构是数组???

分配内存

2)如果我使用指针如何高效的那样。

3)如果C ++ / CLI包装被继续使用我怎么可以通过C#访问它。

这是一个漫长的时间,我的工作和我米没有搞清楚应该怎么填写结构数组在C#。

Follwing code是我揣摩...

元帅code:

面对的一个错误来定义一个扩展非泛型静态类

 公共静态的IntPtr GetIntPtr(此对象OBJ){
            尝试{
                VAR手柄= GCHandle.Alloc(OBJ,GCHandleType.Pinned);
                VAR线程=新主题(()=&GT; {
                    Thread.sleep代码(20000);
                    handle.Free();
                });
                thread.Start();                返回handle.AddrOfPinnedObject();
            }赶上(ArgumentException的){
                VAR PTR = Marshal.AllocHGlobal(Marshal.SizeOf(OBJ));                Marshal.StructureToPtr(OBJ,PTR,FALSE);                返回PTR;
            }
        }        公共静态ŧFromIntPtr&LT; T&GT;(这个IntPtr的PTR){
            如果(PTR == IntPtr.Zero)
                返回默认(T);            回报(T)Marshal.PtrToStructure(PTR的typeof(T));
        }

我如何调用该函数的C ++ code,A链接中给出。<一个href=\"http://stackoverflow.com/questions/30184208/how-to-dynamically-fill-the-structure-which-is-a-pointer-to-pointer-of-arrays-in/30195771?noredirect=1#comment48798363_30195771\">link


解决方案

这是在C#我的结构映射:

  [StructLayout(LayoutKind.Sequential)]
公共结构信息
{
    公共UINT的MsgId;
    公共UINT DLC;
    公共UINT时间间隔;
    公共UINT句柄;
    [的MarshalAs(UnmanagedType.ByValArray,SizeConst = 64)]
    公共字节[]数据;
};

C ++在这里:

 结构信息{
    unsigned int类型的MsgId;
    unsigned int类型DLC;
    无符号整型区间;
    无符号整型句柄;
    unsigned char型数据[64];

};

我在C ++中,需要这样的结构作为参数的方法:

 的externC__declspec(dllexport)的INT _stdcall MessageWrapper(消息* MSG)

这是我如何调用此方法从C#:

 消息帧=新的Message();
            frame.MsgId =(UINT)的MsgId;
            frame.DLC =(UINT)DLC;
            frame.Interval =(UINT)间隔;
            frame.Data =新的字节[64];
            INT rawsize = Marshal.SizeOf(架);
            IntPtr的帧缓冲= Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(帧,帧缓冲,FALSE);

在这里调用方法:

  INT响应= HwWrapper.MessageWrapper卡(framebuffer);

您可能必须在C做了一些修改++,你可以在C#回到这里阅读:

  =帧(消息)(Marshal.PtrToStructure卡(framebuffer的typeof(消息)));
            Marshal.FreeHGlobal卡(framebuffer);

Structure 1:

typedef struct _wfs_cdm_cu_info
{
    USHORT usTellerID;
    USHORT usCount;
    LPWFSCDMCASHUNIT * lppList;
} WFSCDMCUINFO, * LPWFSCDMCUINFO; 

Structure 2:

typedef struct _wfs_cdm_cashunit
{
    USHORT usNumber;
    USHORT usType;
    LPSTR lpszCashUnitName;
    CHAR cUnitID[5];
    CHAR cCurrencyID[3];
    ULONG ulValues;
    ULONG ulInitialCount;
    ULONG ulCount;
    ULONG ulRejectCount;
    ULONG ulMinimum;
    ULONG ulMaximum;
    BOOL bAppLock;
    USHORT usStatus;
    USHORT usNumPhysicalCUs;
    LPWFSCDMPHCU * lppPhysical;
} WFSCDMCASHUNIT, * LPWFSCDMCASHUNIT;

Structure 3:

typedef struct _wfs_cdm_physicalcu
{
    LPSTR lpPhysicalPositionName;
    CHAR cUnitID[5];
    ULONG ulInitialCount;
    ULONG ulCount;
    ULONG ulRejectCount;
    ULONG ulMaximum;
    USHORT usPStatus;
    BOOL bHardwareSensor;
} WFSCDMPHCU, * LPWFSCDMPHCU; 


C# structure:-

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi, Pack = 1)]
public struct WFSCDMPHCU {     [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
 public string lpPhysicalPositionName;[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)]
 public string cUnitID;
 public uint ulInitialCount;
 public uint ulCount;
 public uint ulRejectCount;
 public uint ulMaximum;
 public ushort usPStatus;
 public int bHardwareSensor;
}


[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi, Pack = 1)]
    public struct WFSCDMCASHUNIT {
     public ushort usNumber;
     public ushort usType;         [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
     public string lpszCashUnitName;[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)]
     public string cUnitID;        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=3)]
     public string cCurrencyID;
     public uint ulValues;
     public uint ulInitialCount;
     public uint ulCount;
     public uint ulRejectCount;
     public uint ulMinimum;
     public uint ulMaximum;
     public int bAppLock;
     public ushort usStatus;
     public ushort usNumPhysicalCUs;
     public System.IntPtr lppPhysical;
    }


[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)]
public struct WFSCDMCUINFO {    
 public ushort usTellerID;    
 public ushort usCount;      
 public System.IntPtr lppList;
}

DLLImport

[DllImport(@"Dispenser.dll")]
public static extern int CDM_SetCashUnit(out WFSCDMCUINFO cuinfo);

1)My main problem is How should I marshall or allocate memory for this structure to send data from C# to C++ ,the second and third structure being array of structure???

2)If I use pointer how efficient it would be.

3)If C++/CLI wrapper be used then how I could access it through C#.

It is been a long time I'm working and I m yet to figure out how should I fill the array of structures in C# .

Follwing code is what i try to figure out...

Marshal Code:

Facing an error of "to define an extension non generic static class"

 public static IntPtr GetIntPtr(this object obj) {
            try {
                var handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
                var thread = new Thread(() => {
                    Thread.Sleep(20000);
                    handle.Free();
                });
                thread.Start();

                return handle.AddrOfPinnedObject();
            } catch (ArgumentException) {
                var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));

                Marshal.StructureToPtr(obj, ptr, false);

                return ptr;
            }
        }

        public static T FromIntPtr<T>(this IntPtr ptr) {
            if (ptr == IntPtr.Zero)
                return default(T);

            return (T) Marshal.PtrToStructure(ptr, typeof (T));
        }

A link of C++ code, of how I have called the function is given.link

解决方案

This is my structure mapping in c#:

[StructLayout(LayoutKind.Sequential)]
public struct Message
{
    public uint MsgId;
    public uint DLC;
    public uint Interval;
    public uint Handle;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    public byte[] Data;
};

C++ here:

    struct Message { 
    unsigned int MsgId;
    unsigned int DLC;
    unsigned int Interval;
    unsigned int Handle;
    unsigned char Data[64]; 

} ;

My method in c++ which needs such a structure as a parameter:

extern "C" __declspec(dllexport) int _stdcall MessageWrapper( Message *msg)

Here is how i call this method from C#:

            Message frame = new Message();
            frame.MsgId = (uint)MsgId;
            frame.DLC = (uint)Dlc;
            frame.Interval = (uint)Interval;
            frame.Data = new byte[64];


            int rawsize = Marshal.SizeOf(frame);
            IntPtr frameBuffer = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(frame, frameBuffer, false);

Call the method here:

            int response = HwWrapper.MessageWrapper(frameBuffer);

You may have some modifications made in c++ and you can read them back here in c#:

            frame = (Message)(Marshal.PtrToStructure(frameBuffer, typeof(Message)));


            Marshal.FreeHGlobal(frameBuffer);

这篇关于如何分配内存结构,在C#中的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆