2016-08-02 2 views
1

아래와 같이 두 개의 C++ 구조체가 있습니다. C#에서 DLL 메서드를 호출 할 때 구조체를 가져와야합니다.중첩 된 구조체를 정렬하십시오.

예를 들어, C에서 아래를 정의 할 수 있습니다 ++ 코드 :

struct A 
{ 
    int count; 
    struct B; 
} 

struct B 
{ 
    char* id; 
    char* name; 
} 

C++ 코드는 아래의 방법

A* GetData(); 

나는 C#을에서 호출해야하는 방법을 돌려 다음 서명이 :

IntPtr GetData(); 

이 메소드는 struct A, id 및 C#에서 구조체 B.

에서 이름 난 클래스로 이러한 구조를 정의

[StructLayout(LayoutKind.Sequential)] 

class A 
{ 

    public int count; 
    public IntPtr B; 
} 

[StructLayout(LayoutKind.Sequential)] 

class B 
{ 

    public string id; 
    public string name; 
} 

전 C#에서 호출하는 C++ DLL을 만들었습니다.

중첩 된 구조에서 데이터를 읽으려고하면 읽기 위반 오류가 발생합니다.

어떻게 중첩 된 구조체를 마샬링하여 C# 방식으로 읽을 수 있습니까? 어떻게 ID와 이름을 가진 구조체 B의 멤버에 액세스 할

[DllImport("Win32Project.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] 

public static extern IntPtr GetData(); 

A setting = new A(); 

setting.B = new IntPtr(); 

IntPtr deviceSettingptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(A))); 

IntPtr settingsInfoptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(B))); 

Marshal.StructureToPtr(setting, deviceSettingptr, false); 

Marshal.StructureToPtr(setting.B, settingsInfoptr, true); 

setting.B= settingsInfoptr; 

deviceSettingptr = GetData(); 

setting = (A)Marshal.PtrToStructure(deviceSettingptr, typeof(A)); 

B info = (B)Marshal.PtrToStructure(setting.B, typeof(B)); 

Console.WriteLine(string.Format("Setting count={0}", setting.count)); 
Console.WriteLine(string.Format("Setting id={0}, Setting name={1}", info.id, info.name)); 

아래로

내 C# 코드는?

+0

잠깐,'A.b'는'B' 또는'B'에 대한 포인터입니까? – Luaan

+1

A.B 멤버는 포인터가 아니라 구조체입니다. 대신 B로 선언해야합니다. B의 문자열은 매우 중요한 메모리 관리 문제이며 누군가는 다시 릴리스해야합니다. pinvoke marshaller는이를 수행 할 수 없으므로 IntPtr로 선언하고 Marshal.PtrToStringAnsi()를 사용해야합니다. 어떻게 메모리를 공개할까요, 행운을 빈다. GetData()의 반환 값에 대해서도 똑같은데, 이것은 매달린 포인터라는 높은 확률입니다. C++ 코드를 먼저 개선하고, 그대로 사용할 수 없습니다. –

+0

구조체 B의 문자열을 IntPtr로 선언하고 아래에서 사용하여 데이터를 가져 왔습니다. string id = Marshal.PtrToStringAnsi (info.id); 하지만 빈 문자열이 반환됩니다. –

답변

0

게시 한 코드가 약간 이상해 보입니다. 줄 앞의 모든 것

는 부적절한 것처럼 보입니다. GetData()이 무엇인지 보여주지 않았지만이 방법은을 구조체에 대한 포인터로 반환하는 인 것으로 보입니다. (폐기되기 전에 당신이 변수 setting에했던 것도,이 시점에서)

deviceSettingptr = GetData(); 
setting = (A)Marshal.PtrToStructure(deviceSettingptr, typeof(A)); 

: 그래서 처음에 구조 (아마도 A)를 참조하십시오.

는 그리고 지금 당신은 (아마도) 메모리의 종류 B의 구조를 읽는 것은 setting.B 가리키는 원하는 : 당신의 코드에서

B info = (B)Marshal.PtrToStructure(setting.B, typeof(B)); 

은 당신이 제대로 설정되지 않은 대신 settingsInfoptr을 사용했다.

이제 속성 idinfoname에 액세스 할 수 있습니다 : 아마 누군가가 다시 GetData()에 의해 할당 된 메모리를 해제해야

Console.WriteLine(string.Format("Setting count={0}", setting.count)); 
Console.WriteLine(string.Format("Setting id={0}, Setting name={1}", info.id, info.name)); 

참고.

+0

B 정보 = (B) Marshal.PtrToStructure (setting.B, typeof (B)); Console.WriteLine (string.Format ("설정 ID = {0}, 설정 이름 = {1}", info.id, info.name)); info.id 및 info.name은 문자열 값이 아니라 포인터 값을 제공합니다. –

+0

예 지금 받으 셨습니다. –

관련 문제