2017-01-19 1 views
1

Windows CE 프로그램 및 Compact Framework 2.0에서 C++에서 C#으로 다음 구조체를 마샬링하려고합니다. 현악기의 마샬링에 많은 어려움을 겪고 있습니다.WinCE에서 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# 코드 :

나는 ++ 코드이 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#에서 문자 배열 대신 바이트 []를 사용하십시오. – jdweng

+1

저는 꽤 오래 C++을 사용하지는 않았지만'char []'와'string []'은 동등하지 않습니다. 난 당신이 C# 코드에서 단지'문자열'을 원한다고 생각합니다. – 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는 윈도우 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

Compact Framework 2.0에서 작동합니다. Charset.Ansi가 구현되지 않았습니다. – 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)에서 예외를 throw합니다 (예외 : NotsupportedException). enum CallingConvention에는 하나의 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