2017-01-19 8 views
1

Windows CEプログラムとコンパクトなフレームワーク2.0で、次の構造体をC++からC#にマーシャリングしようとしています。私は文字列のマーシャリングに多くの困難を抱えています。WinCEのC++からc#への構造体のマーシャリング

私はこのC++コードを持っている:

#define Console_Parameters_MAX 50 

struct AllParameters { 
    Parameter Parameters[Console_Parameters_MAX]; 
} ; 

struct Parameter { 
    int Index; 
    int Id; 
    char Value[20]; 
}; 

extern "C" { 
    BOOL GetAllConsoleParameters(AllParameters *pItem); 
} 

をして、これは、対応するC#のコードです:

[StructLayout(LayoutKind.Sequential)] 
public struct AllParameters { 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] 
    public Parameter[] Parameters 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct Parameter { 
    public int Index; 
    public int Id; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] 
    public byte[] Value; 
} 

[DllImport("exemple.dll", SetLastError = true)] 
public static extern bool GetAllConsoleParameters([MarshalAs(UnmanagedType.Struct)] ref AllParameters pItem); 

、これは私がそれを呼び出す方法です:

AllParameters item = new AllParameters(); 
if (AppAPI.GetAllConsoleParameters(ref item)) { 
    var array = item.Parameters; 
} 

私が呼ぶときGetAllConsoleParameters私は例外NotSupportedExceptionを取得します。私は多くの設定を試みましたが、成功しませんでした。

誰でもその達成方法をアドバイスできますか?

ありがとうございます。

+0

のための多くは、のメッセージは何ですか例外? – cubrr

+0

sttringはクラスであり、char配列と同等ではありません。 IN C++文字配列は '\ 0'で終了します。したがって、C#ではchar配列の代わりにbyte []を使用します。 – jdweng

+1

私はかなり長い間C++を使用していませんでしたが、 'char []'と 'string []'は等価ではありません。私は、あなたのC#コードで 'string'だけを望むかもしれないと思います。 System.NotSupportedException メッセージ:コンパクトなフレームワーク2.0との非サポート例外 – Sean

答えて

0

folloようにそれを行うだろう翼私の解決策、C++コード:

/* - not used 
#define Console_Parameters_MAX 50 

struct AllParameters { 
    Parameter Parameters[Console_Parameters_MAX]; 
} ; 
*/ 

struct Parameter { 
    int Index; 
    int Id; 
    char Value[20]; 
}; 

extern "C" { 
    BOOL GetAllConsoleParameters(Parameter pItem[], int size); 
} 

と対応するC#コード:

/* - not used 
[StructLayout(LayoutKind.Sequential)] 
public struct AllParameters { 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] 
    public Parameter[] Parameters 
} 
*/ 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct Parameter { 
    public int Index; 
    public int Id; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] 
    public byte[] Value; 
} 

[DllImport("exemple.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
public static extern bool GetAllConsoleParameters([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] ConsoleParameter[] myStruct, int size); 

とコードの呼び出し:

ConsoleParameter[] item = new ConsoleParameter[50]; 
if (AppAPI.GetAllConsoleParameters(item, 50)) { 
    var array = item; 
} 

おかげで助け

0

これはWindowsデスクトップ上で動作します。あなたは、私がCDECLは、Windows CE上の標準であることをここで読んでいるので、C DLLとC#DLLIMPORT属性にCDECLへの呼び出し規約を変更する必要があります:https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention(v=vs.110).aspx

Cコード:

extern "C" { 
    __declspec(dllexport) BOOL __stdcall GetAllConsoleParameters(AllParameters *pItem) 
    { 
    pItem->Parameters[0].Index = 0; 
    pItem->Parameters[0].Id = 42; 
    CopyMemory(&pItem->Parameters[0].Value[0], "Hello World", 12); 
    pItem->Parameters[1].Index = 1; 
    pItem->Parameters[1].Id = 43; 
    CopyMemory(&pItem->Parameters[1].Value[0], "Hello World 43", 15); 
    return TRUE; 
    } 
} 

C#コード:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
struct Parameter 
{ 
    int Index; 
    int Id; 
    //char Value[20]; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] 
    string Value; 
}; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
struct AllParameters 
{ 
    //Parameter Parameters[Console_Parameters_MAX]; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] 
    Parameter[] Parameters; 
}; 

class Program 
{ 
    [DllImport("MarshalC.dll", CallingConvention = CallingConvention.StdCall)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool GetAllConsoleParameters(ref AllParameters pItem); 

    static void Main(string[] args) 
    { 
     var size = Marshal.SizeOf<AllParameters>(); 
     AllParameters all = new AllParameters(); 
     bool result = GetAllConsoleParameters(ref all); 
    } 
} 
+0

作業 – mircoso

+0

私は "C:¥Program Files(x86)¥Microsoft.NET¥SDK¥CompactFramework¥v2.0¥WindowsCE¥mscorlib.dll"を試して、このライブラリにはCdeclは含まれていません。多分私のライブラリは時代遅れですか? – mircoso

0

私はこの

 [StructLayout(LayoutKind.Sequential)] 
     public struct AllParameters { 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] 
      public Parameter[] Parameters; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct Parameter { 
      public int Index; 
      public int Id; 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] 
      public byte[] Value; 
     } 

     [DllImport("exemple.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] 
     public static extern bool GetAllConsoleParameters(ref IntPtr pItem); 


     static void Main(string[] args) 
     { 
      AllParameters allParameters = new AllParameters(); 
      allParameters.Parameters = new Parameter[50]; 
      IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(allParameters)); 

      int z = Marshal.SizeOf(allParameters); 

      if (GetAllConsoleParameters(ref ptr)) 
      { 
       Marshal.PtrToStructure(ptr, allParameters); 
       Parameter[] parameters = allParameters.Parameters; 
      } 

     } 
+0

解決方法を試してみますが、Marshal.SizeOf(allParameters)で例外をスローします(例外:NotsupportedException)。列挙型CallingConventionには1つの要素WinApiのみが含まれます。 (私はFramework:Compact Framework 2.0とVS 2008を使用します)。理由を理解できません.... – mircoso

+0

最新のコードと構造を使用してください。元の投稿コードで同様のエラーが発生し、変更が加えられました。ポストされたコードは、このエラーをこれ以上与えません。 'z'の値は1400 = 50 * 28で正しいです。そのため、コードはLPTR ptrを、管理されていないメモリ空間にある1400バイトのメモリの事前割り当てブロックに渡します。 – jdweng

+0

代わりにこれを試すことができます:int z = Marshal.SizeOf(allParameters.GetType()); – jdweng

関連する問題