我现在已经把我的c结构编组到ref class了一段时间了。
我需要跨越非托管c数据到c#的边界,所以我用c代码和一些ref类构建一个混合模式dll。我在我的混合模式dll中调用了一些c函数,它填充了c结构。另外,我编写了一个包装器引用类,以便为我的c#项目提供数据。 现在我需要将非托管数据“转换”为我的托管re类。这对某些人(对我来说)不明原因而失败。
这是C ++ / CLI代码:
mymanaged cli_struct;
myunmanaged c_Struct;
bool res = fillupstruct(&c_struct);
if(res)
{
// copy unmanaged structure to managed
System::IntPtr ptr = System::IntPtr(&c_struct);
cli_struct = (mymanaged^)Marshal::PtrToStructure(ptr, mymanaged->GetType()); // <----- this call fails ...
}
据我所知,这是它应该如何运作的。但我总是得到这个错误信息:
mscorelib.dll中的System.TypeLoadexception
ZusätzlicheInformationen:Das Feld“m_State”des Typs“mymanaged”kann nicht gemarshallt werden:DieTypendefinitionfürdiesesFeldenthältLayoutinformationen,hat jedocheineuüliggeverwaltete/ nicht verwaltete Typenkombination oder kann nicht gemarshallt werden。
(translatad to english:附加信息:“托管”字段的“m_State”无法编组:此字段的类型定义包含布局信息,但具有无效的托管/非托管类型组合或无法编组。)
这是我的C ++ / CLI结构:
[StructLayoutAttribute(LayoutKind::Explicit)] ///, Pack=2)]
public ref class mymanaged
{
public:
[FieldOffset(0)]
Versions m_Ver;
[FieldOffset(8)]
State m_State;
[FieldOffset(72)]
Info m_MoDta;
[FieldOffset(136)]
Parameters m_Param;
[FieldOffset(264)]
Settings m_Set;
[FieldOffset(312)]
[MarshalAs(UnmanagedType::ByValArray, SizeConst = 3)]
array<T_RmD^>^ m_MSys; // --> "T_RmD m_MSys[3];" in c-struct
[FieldOffset(440)]
PARAM m__Params;
private:
void InitializeInstanceFields()
{
m_MSys = gcnew array<T_RmD^>(3);
}
public:
ToolData()
{
InitializeInstanceFields();
}
};
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct Versions
{
[FieldOffset(0)]
UInt16 m_hw_majorVersion;
[FieldOffset(sizeof(UInt16))]
UInt16 m_hw_minorVersion;
[FieldOffset(2*sizeof(UInt16))]
UInt16 m_majorVersion;
[FieldOffset(3*sizeof(UInt16))]
UInt16 m_minorVersion;
};
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct State
{
[FieldOffset(0)]
UInt16 STATUS;
[FieldOffset(2)]
UInt16 KOMMAND;
[FieldOffset(4)]
UInt16 ERR;
[FieldOffset(6)]
UInt16 WAR;
[FieldOffset(8)]
UInt16 TEM_1;
[FieldOffset(10)]
UInt16 TEM_2;
[FieldOffset(12)]
UInt16 TEM_3;
[FieldOffset(14)]
UInt16 TEM_4;
[FieldOffset(16)]
[MarshalAs(UnmanagedType::LPArray, SizeConst = 4)]
inline_array <UInt32,4> res; --> simply a uint16 [4] in c-struct
[FieldOffset(32)]
UInt16 cccc;
[FieldOffset(34)]
UInt16 AW;
[FieldOffset(36)]
UInt16 PMs_1;
[FieldOffset(38)]
UInt16 PMs_2;
[FieldOffset(40)]
UInt16 PKo;
[FieldOffset(42)]
UInt16 Tp;
[FieldOffset(44)]
UInt16 Aga;
[FieldOffset(46)]
UInt16 Alog_1;
[FieldOffset(48)]
UInt16 Alog_2;
[FieldOffset(50)]
UInt16 Alog_3;
[FieldOffset(52)]
UInt16 Alog_4;
[FieldOffset(54)]
UInt16 Alog_5;
[FieldOffset(56)]
UInt16 Alog_6;
[FieldOffset(58)]
UInt16 ResPtr;
[FieldOffset(60)]
UInt16 AddBelKen;
};
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct Info
{
[FieldOffset(0)]
UInt16 RotNU;
[FieldOffset(2)]
UInt16 MotR;
[FieldOffset(4)]
UInt16 MotH;
[FieldOffset(6)]
UInt16 Momkon;
[FieldOffset(8)]
UInt16 amp_a;
[FieldOffset(10)]
UInt16 LeerA;
[FieldOffset(12)]
UInt16 LeerB;
[FieldOffset(14)]
UInt16 FP;
[FieldOffset(16)]
UInt16 MinD;
[FieldOffset(18)]
UInt16 MotP;
[FieldOffset(20)]
Int16 MomSh;
// TODO Bitfield offset ???? --> these are bitfields in c-code
// i have no clue what to do with these...
[FieldOffset(??)]
UInt16 I2Gr; // c-code: unsigned short I2Gr:8;
[FieldOffset(??)]
UInt16 I2TK; // c-code: unsigned short I2TK:8;
[FieldOffset(24)]
UInt16 GetUes;
[FieldOffset(26)]
UInt16 MinMoS;
[FieldOffset(28)]
UInt16 SGr;
[FieldOffset(30)]
UInt16 AbD;
[FieldOffset(32)]
UInt16 MomKf;
[FieldOffset(34)]
UInt16 m_HaUG;
[FieldOffset(36)]
UInt16 m_HaOG;
[FieldOffset(38)]
[MarshalAs(UnmanagedType::LPArray, SizeConst = 12)]
inline_array<UInt16,12> Reserviert; ///< Reserve --> simply a uint16 [12] in c-struct
[FieldOffset(62)]
UInt16 _Cr;
};
[System::Runtime::CompilerServices::UnsafeValueType]
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct Parameters
{
[FieldOffset(0)]
UInt16 m_EM;
[FieldOffset(2)]
UInt16 m_PUPm;
[FieldOffset(4)]
UInt16 m_ALW;
[FieldOffset(6)]
UInt16 m_RMno;
[FieldOffset(8)]
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = 16)]
inline_array<Char,16> m_WST;
[FieldOffset(24)]
UInt32 m_S;
[FieldOffset(28)]
UInt16 m_ST;
[FieldOffset(30)]
UInt16 m_Res;
[FieldOffset(32)]
UInt16 m_mmnar;
[FieldOffset(34)]
UInt16 m_mmxar;
[FieldOffset(36)]
UInt16 m_dar;
[FieldOffset(38)]
UInt16 m_AMaR;
[FieldOffset(40)]
UInt16 m_AMh;
[FieldOffset(42)]
UInt16 m_APh;
[FieldOffset(44)]
UInt16 m_So;
[FieldOffset(46)]
UInt16 m_WDn;
[FieldOffset(48)]
UInt16 m_WDx;
[FieldOffset(50)]
UInt16 m_WMN;
[FieldOffset(52)]
UInt16 m_WMX;
[FieldOffset(54)]
UInt16 m_WMS;
[FieldOffset(56)]
UInt16 m_WBw;
[FieldOffset(58)]
UInt16 m_WSw;
[FieldOffset(60)]
UInt16 m_WKn;
[FieldOffset(62)]
UInt16 m_WKx
[FieldOffset(64)]
[MarshalAs(UnmanagedType::ByValArray, SizeConst = 31)]
inline_array<UInt16,31> Reserviert;
[FieldOffset(126)]
UInt16 m_C;
};
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct og_spec
{
[FieldOffset(0)]
UInt16 m_av;
[FieldOffset(2)]
Int16 m_dr;
[FieldOffset(4)]
UInt32 m_ef;
[FieldOffset(8)]
float m_val;
};
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct Settings
{
[FieldOffset(0)]
UInt16 m_MoKW;
[FieldOffset(2)]
UInt16 m_reserved;
[FieldOffset(4)]
UInt16 m_StO;
[FieldOffset(6)]
UInt16 m_res1;
[FieldOffset(8)]
UInt16 m_res2;
[FieldOffset(10)]
UInt16 m_Me1Kw;
[FieldOffset(12)]
UInt16 m_Me2Kw;
[FieldOffset(16)]
og_spec m_og;
[FieldOffset(28)]
UInt16 m_C;
};
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct PARAM
{
[FieldOffset(0)]
Int16 TE_AOs;
[FieldOffset(2)]
UInt16 TE_AF;
[FieldOffset(4)]
UInt16 AOf;
[FieldOffset(6)]
UInt16 AFa;
[FieldOffset(8)]
UInt32 TBc;
};
[StructLayoutAttribute(LayoutKind::Auto)]
public value class TSFlags
{
public:
bool TSgn;
UInt32 all;
};
[StructLayoutAttribute(LayoutKind::Explicit)]
public value struct _parts
{
public:
[FieldOffset(0)]
UInt32 Cal;
[FieldOffset(4)]
UInt32 Of;
[FieldOffset(8)]
UInt32 SN;
[FieldOffset(12)]
UInt32 SWV;
[FieldOffset(16)]
UInt32 Rge;
[FieldOffset(20)]
UInt32 Anre;
[FieldOffset(24)]
TSFlags Fl;
};
[StructLayoutAttribute(LayoutKind::Auto)]
public value struct T_RmD
{
public:
_parts ^parts;
[MarshalAs(UnmanagedType::LPArray, SizeConst = 2)]
inline_array<UInt32,2> RmD;
};
正如你所看到的那样,我已经把档案库放在了各处。我使用这个来从我的非托管结构中“记录”它:
printf("Offset Of %s: \t\t%lu\n", VNAME(m_Versions), FIELD_OFFSET(DataType, m_Ver));
// here fro reference from some windows headers:
#define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field))
#define VNAME(x) #x
我写下了这些值并将它们转移到托管结构中。
注意:“inline_array”来自: 由Mark Hall编写并由Shaun改进的inline_array模板 米勒:https://blogs.msdn.microsoft.com/branbray/2005/07/20/some-notes-about-mixed-types/
还有一件事是我不知道如何处理两个位域变量...
我现在有点无能为力了。请有人帮帮我吗?
顺便说一句:我也没试过(C ++ / CLI):
GCHandle handle = GCHandle::Alloc(tdata, GCHandleType::Pinned);
try
{
IntPtr pointer = handle.AddrOfPinnedObject();
fillupstruct((DataType*)(void*)pointer);
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}
}
我没有直接将函数和结构直接映射到C#的原因是c代码中存在更多复杂性,我想完全隐藏在C#代码中。