c# 구조체 <-> mfc 구조체


사실 c#에서 구조체따위!!! 사용하지 않습니다.
거의 다 class 로 만들어서 사용하죠.


c# 에서 구조체는 Value Type 입니다. 클래스는 reference 형입니다. 구조체는 단순히 데이터의 집합이기때문에 실제적을 값을 복사/대입 등등이 벌어지나 클래스는 메모리 주소만 바뀌기 때문에 실제 연산시 구조체보다 클래스가 월등한 속도의 차이를 보여주며 구조체는 많은 데이터를 입출력하기엔 스택을 너무 잡아먹어서 연산이 점점 느려지기 때문입니다.


mfc 혹은 c++ 에서 아래와 같은 구조체를 선언했다고 칩시다.

struct Test_Struct
{
      public float m_float[4];
      public unsinged short meter;
      public byte m_byte[8];
} ;


여기서 중요한점은 구조체를 꼭 패킹을 해주어야 합니다.

#pragma pack(1)

이놈을 선언해줘야 하죠.

Visual C++ 에서는 기본적으로 4바이트씩 할당이 됩니다. 즉 1바이트를 선언해도 실제적으로 4바이트를 먹어버리는거죠. sizeof(구조체) 했을때 크기의 차이를 보이는건 이때문입니다. 이것을 방지하기 위해 패킹을 #pragma pack(1)로 해주어서
1바이트는 진짜 1바이트만 사용하게 바꿔줘야 합니다.

그리고 함수에서 사용을 합니다.

extern "C" __declspec(dllexport) int DLL_CalMyStruct(Test_Struct * test)
{
     .
     .
     .
}

자 이제 c# 쪽에서도 구조체를 선언해줍시다.

[StructLayout(LayoutKind.Sequential, Pack = 1), Serializable]
public struct TestStruct
{
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public float[] m_float;   
        public ushort meter;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] m_byte;
} ;

c# 쪽에서도 패킹을 해주었군요.

다 끝났습니다.

이제 dll 함수를 작성합니다.


[DllImport("testdll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DLL_CalMyStruct(ref TestStruct pStruct);

저는 그냥 ref 형으로 받았습니다만... out 형을 쓰는게 더 좋을거 같습니다. ref 형은 입출력이 가능하지만 out형은 출력만 가능합니다...

그리고

위의 함수를 호출해주면 pStruct로 값이 복사되어 나오게 됩니다.

안타깝게도 class 를 바로 사용할수는 없습니다. 구조체로 받아서 클래스로 복사하는 방법은 있으나 의미없는 짓이라 패스합니다....





댓글

이 블로그의 인기 게시물

c# GDI+ 꺼져!! BufferedGraphics

c# 에서 C++ dll 사용하기

c# string 에서 mfc의 LPCTSTR간의 변환