Location | Tag | Media  ||  A | P

-       C++ Struct 1

typedef struct _DATASTRUCT {

        wchar_t name[20];

        wchar_t path[255];

        int level;

DATASTRUCT, *LPDATASTRUCT;

 

-    C# Struct 1

[StructLayout(LayoutKind.SequentialCharSet=CharSet.Unicode)]

public struct DATASTRUCT

{

[MarshalAs(UnmanagedType.ByValTStrSizeConst = 20)]

public string name;

      

[MarshalAs(UnmanagedType.ByValTStrSizeConst = 255)]

public string path;

 

public int level;

}

 

C++  C# 의 구조체는 앞과 같다.

-    C# 예제 코드

 

int MAX_COUNT = 10;

DATASTRUCT[] dataStructs;

 

 

 [DllImport(@".\SendDataObject.dll"CharSet = CharSet.Unicode)]

private static extern int GetDatas(DATASTRUCT[] dataStructintbufSizeCountref IntPtr returnPtr);

 

.

.

 

IntPtr returnPtr = IntPtr.Zero;

 

dataStructs = new DATASTRUCT[MAX_COUNT];

 

// 구조체 배열 초기화 또는 기타 처리 할 것

 

GetDatas(dataStructsMAX_COUNTref returnPtr);

 

int next = 0;

for (int index = 0; index < MAX_COUNTindex++)

{

DATASTRUCT resultData = (DATASTRUCT)Marshal.PtrToStructure(newIntPtr(returnPtr.ToInt32() + next), dataStruct.GetType());

 

next += Marshal.SizeOf(dataStruct.GetType());

}

.

.

 

-    C++  예제 코드

 

SEND_DATASTRUCTURE_API int GetDatas(LPDATASTRUCT lpDataStructint bufSizeCount,HRESULTdataStructPtr)

{

 

        try

        {

               dataStructPtr = (HRESULT)lpDataStruct;

       

 

.

.

.

 

        }

        catch (...)

        {

               SCDI_TRACE(L"[SEND_DATASTRUCTURE_API] GetDatas() Error");

               return -1;

        }

 

        return 0;

}

 

C++ 에서 LPDATASTRUCT 구조체에 다수의 구조체 정보를 저장해 놓을 수 있다그렇다면 C# 에서는 그 값을 꺼내서 사용 해야 하는데. C# 에서 ref 를 이용하면 되지 않겠는가라고 생각 하실 겁니다해보았으나 결과는Collection  1 개만 넘어와서 그 이상의 값을 꺼내 올 수 가 없었다.

 

DATASTRUCT resultData = (DATASTRUCT)Marshal.PtrToStructure(newIntPtr(returnPtr.ToInt32() + next), dataStruct.GetType());

 

next += Marshal.SizeOf(dataStruct.GetType());

 

C# 에서는 바로 앞의 코드가 핵심이다Marshal.PtrToStructure 를 이용해서 해당 주소값의 위치에서 구조체를 꺼내 온다.

 

본 예제 에서는 10 개의 배열 구조체를 만들어 사용했다.

 

Marshal.SizeOf(dataStruct.GetType()) 는 구조체의 SizeOf 로 해당 Size 만큼 주소 값을 이동 시키면서 구조체를 꺼내 오면 된다.

 

추가 내용 : 

앞에서와 같은 방법도 방법이였지만 그래서 DLL Import 부분을 다음과 같이 수정해 보았다[Out을 사용한 것이다.

 

[DllImport(@".\SendDataObject.dll"CharSet = CharSet.Unicode)]

private static extern int GetDatas([OutDATASTRUCT[] dataStructintbufSizeCountref IntPtr returnPtr);

 

 

그리 하였더니 깔끔하게 값들을 잘 가져왔다.

 

GetDatas([OutDATASTRUCT[] dataStructint bufSizeCountref IntPtr returnPtr);

 

즉, 앞에서 포인터 값을 이용하는 방식을 사용할 필요가 없었다. 하지만 앞에서와 같은 방식도 어디선가 쓰일 일이 때론 있을 것이다.

Posted by Bestend
: