C++ cli StructureToPtr未将本机结构中的基元类型字段正确复制到ref结构
我有一个本机结构(它相当大,所以我必须使用新的关键字来实例化,下面只是做一个MCVE,我不能更改该结构,因为它是作为外部依赖项提供的) 我想将NativeStruct转换为托管对象,所以我定义了一个ref struct来镜像它,这也使用了两个枚举,如下所示C++ cli StructureToPtr未将本机结构中的基元类型字段正确复制到ref结构,c++-cli,C++ Cli,我有一个本机结构(它相当大,所以我必须使用新的关键字来实例化,下面只是做一个MCVE,我不能更改该结构,因为它是作为外部依赖项提供的) 我想将NativeStruct转换为托管对象,所以我定义了一个ref struct来镜像它,这也使用了两个枚举,如下所示 public enum struct EnumOrderPriceTypeType { AnyPrice = (Byte)'1', LimitPrice = (Byte)'2', BestPrice = (Byte)'
public enum struct EnumOrderPriceTypeType
{
AnyPrice = (Byte)'1',
LimitPrice = (Byte)'2',
BestPrice = (Byte)'3',
LastPrice = (Byte)'4',
LastPricePlusOneTicks = (Byte)'5',
LastPricePlusTwoTicks = (Byte)'6',
LastPricePlusThreeTicks = (Byte)'7',
AskPrice1 = (Byte)'8',
AskPrice1PlusOneTicks = (Byte)'9',
AskPrice1PlusTwoTicks = (Byte)'A',
AskPrice1PlusThreeTicks = (Byte)'B',
BidPrice1 = (Byte)'C',
BidPrice1PlusOneTicks = (Byte)'D',
BidPrice1PlusTwoTicks = (Byte)'E',
BidPrice1PlusThreeTicks = (Byte)'F'
};
public enum struct EnumDirectionType
{
Buy = (Byte)'0',
Sell = (Byte)'1'
};
[StructLayout(LayoutKind::Sequential)]
public ref struct ManagedStruct
{
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 11)]
String^ BrokerID;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 13)]
String^ InvestorID;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 31)]
String^ InstrumentID;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 13)]
String^ OrderRef;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 16)]
String^ UserID;
EnumOrderPriceTypeType OrderPriceType;
EnumDirectionType Direction;
double LimitPrice;
};
然后我使用StructureToPtr
将本机对象复制到托管对象,并使用WriteLine
测试复制是否成功
NativeStruct *native = new NativeStruct();
ManagedStruct^ managed = gcnew ManagedStruct();
managed->LimitPrice = 95.5;
managed->BrokerID = "666666";
Marshal::StructureToPtr(managed, IntPtr(native), false);
int i;
for (i = 0; i < 11; i++)
Console::Write(native->BrokerID[i]);
Console::WriteLine();
Console::WriteLine(native->LimitPrice);
Console::WriteLine(L"Hello ");
Console::ReadLine();
NativeStruct*native=new NativeStruct();
ManagedStruct^managed=gcnew ManagedStruct();
管理价格=95.5;
托管->BrokerID=“666666”;
封送:StructureToPtr(托管,IntPtr(本机),false);
int i;
对于(i=0;i<11;i++)
控制台::Write(本机->BrokerID[i]);
控制台::WriteLine();
控制台::WriteLine(本机->限价);
控制台:WriteLine(L“Hello”);
控制台::ReadLine();
我的问题是为什么LimitPrice
没有成功复制?我已经为此奋斗了一周,欢迎任何帮助。非常感谢。仅当托管结构和本机结构完全匹配时,Marshal::StructureToPtr()才能正常工作。到目前为止,验证这一点的最简单方法是检查结构的尺寸,它们必须相同。因此,请将此代码添加到您的程序中:
auto nlen = sizeof(NativeStruct);
auto mlen = Marshal::SizeOf(ManagedStruct::typeid);
System::Diagnostics::Debug::Assert(nlen == mlen);
卡布姆。本机结构需要96个字节,托管结构需要104个字节。后果是可怕的,你破坏了内存,这比LimitPrice成员值被复制到错误的偏移量有更多不愉快的副作用
解决这一问题的两种基本方法。您只需使用唯一的值填充所有托管结构成员,并检查本机结构中第一个值错误的成员。之前的成员是错误的。继续走,直到你再也找不到卡布姆为止。或者,您可以编写在本机结构成员上使用offsetof()的代码,并将它们与Marshal::offsetof()进行比较
为了省去您的麻烦,问题在于枚举声明。它们在本机结构中的大小为1字节,但托管版本的大小为4字节。修正:
public enum struct EnumOrderPriceTypeType : Byte
及
注意添加了
:Byte
,以强制枚举占用1字节的存储空间。需要注意的是,一个接一个地复制成员而不是使用Marshal::StructureToPtr()会更快,并且会为您节省一周的麻烦。您真是个救命稻草!!谢谢我已经学会了调试技巧。
public enum struct EnumOrderPriceTypeType : Byte
public enum struct EnumDirectionType : Byte