C++ 구조체 포인터의 값을 C# 구조체 배열로 가져오기
- C++ Struct 1
typedef struct _DATASTRUCT {
wchar_t name[20];
wchar_t path[255];
int level;
} DATASTRUCT, *LPDATASTRUCT;
|
- C# Struct 1
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct DATASTRUCT
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 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[] dataStruct, intbufSizeCount, ref IntPtr returnPtr);
.
.
IntPtr returnPtr = IntPtr.Zero;
dataStructs = new DATASTRUCT[MAX_COUNT];
// 구조체 배열 초기화 또는 기타 처리 할 것
GetDatas(dataStructs, MAX_COUNT, ref returnPtr);
int next = 0;
for (int index = 0; index < MAX_COUNT; index++)
{
DATASTRUCT resultData = (DATASTRUCT)Marshal.PtrToStructure(newIntPtr(returnPtr.ToInt32() + next), dataStruct.GetType());
next += Marshal.SizeOf(dataStruct.GetType());
}
.
.
|
- C++ 예제 코드
SEND_DATASTRUCTURE_API int GetDatas(LPDATASTRUCT lpDataStruct, intbufSizeCount, HRESULT& dataStructPtr)
{
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([Out] DATASTRUCT[] dataStruct,int bufSizeCount, ref IntPtr returnPtr);
|
그리 하였더니 깔끔하게 값들을 잘 가져왔다.
GetDatas([Out] DATASTRUCT[] dataStruct, int bufSizeCount, ref IntPtrreturnPtr);
|
즉, 앞에서 포인터 값을 이용하는 방식을 사용할 필요가 없었다. 하지만 앞에서와 같은 방식도 어디선가 쓰일 일이 때론 있을 것이다.
댓글
댓글 쓰기