值类型在C ++/C#中构造数组元素 [英] value type structures array elements in C++/C#

查看:90
本文介绍了值类型在C ++/C#中构造数组元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,

经过大量的网络搜索并尝试了不同的方法之后,我仍然无法解决以下问题:

我写了一个c ++托管的dll,该dll可用作旧式c代码的包装器. C代码使用许多结构,这些结构中充满了来自主机系统的数据.

我需要处理此数据的最终GUI应用程序用C#编写.

我的c结构:

Hi All,

After a lot of searching the web and trying different things, I am still no closer to solving the following:

I have written a c++ managed dll that is supposed to act as a wrapper for legacy c code. The c code uses a lot of structures that is filled with data from a host system.

My final GUI application that needs to process this data is written in C#

My c structure:

typedef struct
{
	unsigned short	u16_RecordType;
	unsigned short	u16_RecordCode;
	char		c_MessageType;
	unsigned char	uc_Filler;
	unsigned long	u32_MessageCode;
	char		c_InfoMessage[3][24];
	unsigned short	u16_CheckSum;

} THE_C_STRUCT;



我在c ++ dll中声明为:



Which I have declared in my c++ dll as:

[StructLayoutAttribute(LayoutKind::Sequential, Pack=1)]
public value struct MyManagedStruct
{
	unsigned short	u16_RecordType;
	unsigned short	u16_RecordCode;
	char		c_MessageType;
	unsigned char	uc_Filler;
	unsigned long	u32_MessageCode;
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=72)]
	static char	^c_MessageLines = gcnew char[3][24]; 
	unsigned short	u16_CheckSum;
};



然后是C ++代码,使用旧版C函数获取数据.请注意,我使用通用函数将数据的字节数组转换为结构对象.到目前为止,此功能在所有其他结构上均能完美运行.



And then the c++ code to get me the data using the legacy C function. Notice that I use a generic function to convert the byte array of data to the structure object. This function has up to now worked perfectly on all other structures.

Object ^MyWrapperClass::ByteArrayToStructure(array<unsigned char> ^bytearray, int offset, Type ^objType)
{
    Object ^returnObj;
    int len = Marshal::SizeOf(objType);
    IntPtr intPtr = Marshal::AllocHGlobal(len);
            
    Marshal::Copy(bytearray, offset, intPtr, len);
    returnObj = Marshal::PtrToStructure(intPtr, objType);
    Marshal::FreeHGlobal(intPtr);

    return returnObj;
}

int MyWrapperClass::GetStructure([Out] Wrapper_Record %p_s_RecordData)
{
	int i_RC;
    
    Type ^t_RecordType = p_s_RecordData.GetType();
    array<unsigned char> ^uc_RecordDataArr = gcnew array<unsigned char>(Marshal::SizeOf(p_s_RecordData));
    pin_ptr<unsigned char>	pp_RecordBuffer = &uc_RecordDataArr[0];

    // call the C function to get the data into the byte array
    i_RC = LC_GetRecord(pp_RecordBuffer);
    if (I_RC == SUCCESS)
    	p_s_RecordData = (Wrapper_Record)ByteArrayToStructure(uc_RecordDataArr, 0, t_RecordType);
    	
    return I_RC;
}



最后,我从我的C#代码中调用dll:



Finally, I am calling the dll from my c# code:

Wrapper_Record wrapperRecord;
MyWrapperClass s = new MyWrapperClass();

int i = s.GetStructure(out wrapperRecord);



我的问题:
1.调试函数ByteArrayToStructure()时, len 的值为10! (该结构应该是84个字节吗?)
2.我怀疑结构中的数组有问题,因此我将结构更改为:



My problem:
1. When debugging the function ByteArrayToStructure(), the value of len is 10! (the structure is supposed to be 84 bytes?)
2. I suspected the array in the structure is the problem, so I changed the structure to:

[StructLayoutAttribute(LayoutKind::Sequential, Size=72, Pack=1)]
public value struct Message_Lines
{
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=24)]
	//static array<char>^ c_MessageLine1; 
	static char	^c_MessageLine1 = gcnew char[24]; 
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=24)]
	//static array<char>^ c_MessageLine2; 
	static char	^c_MessageLine2 = gcnew char[24]; 
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=24)]
	//static array<char>^ c_MessageLine3; 
	static char	^c_MessageLine3 = gcnew char[24]; 
};

[StructLayoutAttribute(LayoutKind::Sequential, Pack=1)]
public value struct MyManagedStruct
{
	unsigned short		u16_RecordType;
	UINT16			u16_RecordCode;
	CHAR			c_MessageType;
	unsigned char		uc_Filler;
	UINT16			u32_MessageCode;
	//[MarshalAs(UnmanagedType::ByValArray,SizeConst=72)]
	//static char	^c_MessageLines = gcnew char[3][24]; 
	Message_Lines		s_MessagLines;
	unsigned short		u16_CheckSum;
};



因此解决了长度问题,但是当查看我的输出对象时,将填充结构字段,但Message_Lines结构值全为零.我在调试中确认在调用ByteArrayToStructure()之前已正确填充了字节数组.

实现此结构并正确填充返回对象的正确方法是什么?
我是否正确使用了Marshal :: PtrToStructure?
有没有人能提供一个很好的链接,让我可以了解有关以数组为元素的编组结构的更多信息?
请帮忙!



So the length issue was solved, but when looking at my output object, the structure fields are populated, but the Message_Lines structure values are all zero. I confirmed in debugging that the byte array is populated correctly before calling ByteArrayToStructure().

What is the correct way of implementing this structure and properly populate the return object?
Am I using Marshal::PtrToStructure correctly?
Does anybody have a good link where I can learn more about marshalling structures that have arrays as elements?
Please help!

推荐答案

看看: ^ ]

为什么不创建混合模式C ++/CLI dll?声明方便在c#中使用的结构,只需将其从原始c结构复制到新结构中即可.

最好的问候
Espen Harlinn
Have a look at:Using ACE with C++ CLI[^]

Why not create a mixed mode C++/CLI dll? Declare structures that are convenient to use in c# and just copy from the original c structures to your new structures ...

Best regards
Espen Harlinn



我没有在C#中使用编组,所以我只是在暗中暗中刺刺,但是有什么特殊的原因为什么要使用static?也许这是您问题的根源?之所以得出这个结论,是因为我看到了
Hi,
I haven''t used marshalling in C#, so I am just taking a stab in the dark with this but is there any particular reason why you are using static? Maybe that is the root of your problem? The reason why I come to this conclusion is because I see this here:

A static method, field, property, or event is callable on a class even when no instance of the class has been created. If any instances of the class are created, they cannot be used to access the static member. Only one copy of static fields and events exists, and static methods and properties can only access static fields and static events. Static members are often used to represent data or calculations that do not change in response to object state; for instance, a math library might contain static methods for calculating sine and cosine.

Hope that helps...


这篇关于值类型在C ++/C#中构造数组元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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