复杂的c struct到ref class - 不能编组

时间:2016-03-07 08:52:05

标签: c# marshalling unmanaged managed mixed-mode

我现在已经把我的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#代码中。

0 个答案:

没有答案