C/C++ 구조체와 함수를 C# 에서 사용하기 (수정1)

01 14, 2007 02:17
 

C/C++ 구조체와 함수를 C# 에서 사용하기

기존의 C/C++ 의 구조체와 함수들을 C# 의 클래스로 캡슐화하는 작업을 설명드립니다.

먼저, C/C++ 에서 DLL 프로젝트를 생성합니다. (프로젝트 이름을 'BND.Native' 라고 하면 출력물은 'BND.Native.dll' 이 됩니다.)


1단계: C/C++ 구조체 정의 (MD5.h)

typedef struct mD5Context
{
    UINT state[4];   /* state (ABCD) */
    UINT count[2];   /* number of bits, modulo 2^64 (lsb first) */
    BYTE buffer[64]; /* input buffer */
}

MD5Context;

구조체 내부에 고정 크기의 배열이 정의되어 있습니다.


2단계: C/C++ 함수 정의 (MD5.cpp)

void MD5Init(MD5Context * context)
{
    ...
}

void MD5Update(MD5Context * context, BYTE * input, UINT input_size)
{
    ...
}

void MD5Final(MD5Context * context, BYTE * output_digest)
{
    ...
}

C/C++ 언어답게(?) 포인터를 마구 사용하고 있습니다.


3단계: C/C++ 함수 선언 (MD5.h)

extern "C" __declspec(dllexport) void MD5Init(MD5Context * context);
extern "C" __declspec(dllexport) void MD5Update(MD5Context * context, BYTE * input, UINT input_size);
extern "C" __declspec(dllexport) void MD5Final(MD5Context * context, BYTE * output_digest);

함수들을 DLL 외부로 노출합니다.
이를 위해서 #include <Windows.h> 라인을 추가해야 합니다.


이상의 3단계를 작업한 후 컴파일하여 C/C++ DLL 을 생성합니다.
다음으로 C# 프로젝트를 생성합니다.
C# 프로그램에서 C/C++ DLL 을 참조하기 위해  [C# 프로젝트의 속성] - [빌드 이벤트] - [빌드 후 이벤트 명령줄] 에 다음을 추가합니다.


COPY /Y "$(SolutionDir)BND.Native\$(ConfigurationName)\BND.Native.dll" "$(TargetDir)BND.Native.dll"


C/C++ DLL 파일을 C# 프로젝트의 출력 디렉토리로 복사해 오는 것입니다.
이를 위해서 프로젝트 '종속성'에 'BND.Native' 프로젝트를 추가해야 합니다.


4단계: 구조체 캡슐화

    public class MD5Calculator
    {

        // C/C++ 의 구조체와 동일한 형태가 되도록 정의합니다.
        public struct MD5Context
        {

            [MarshalAs(UnmanagedType.ByValArray, SizeConst =  4)] public UInt32[] state;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst =  2)] public UInt32[] count;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] buffer;

        }

        // 클래스 내부에 구조체 인스턴스를 캡슐화합니다.
        private MD5Context mContext = new MD5Context();

        // 구조체를 초기화하는 코드를 생성자 내부에 작성합니다.
        public MD5Calculator()
        {
            /* 따로 new 하지 않아도 이미 공간이 확보되어 있음.
            mContext.state = new UInt32[4];
            mContext.count = new UInt32[2];
            mContext.buffer = new byte[64];
            */
        }


C/C++ 에서 정의한 구조체와 동일한 구조체를 정의하고, 그 인스턴스를 정의하고, 초기화 코드를 작성하였습니다.
이 작업들을 편의상 하나의 클래스(MD5Calculator) 내에 캡슐화하였습니다.


5단계: 함수 참조 선언

        // C언어 함수들
        [DllImport("BND.Native.dll")] extern public static void MD5Init(ref MD5Context ctx);
        [DllImport("BND.Native.dll")] extern public static void MD5Update(ref MD5Context ctx, byte[] input, int input_size);
        [DllImport("BND.Native.dll")] extern public static void MD5Final(ref MD5Context ctx, byte[] output_digest);


각종 포인터 파라미터가 위와 같이 매핑됩니다.


 

6단계: 함수 캡슐화

        public void Initial()
        {
            MD5Init(ref mContext);
        }

        public void Update(byte[] input, int input_size)
        {
            MD5Update(ref mContext, input, input_size);
        }

        public byte[] Final()
        {
            byte[] output_digest = new byte[16];
            MD5Final(ref mContext, output_digest);
            return output_digest;
        }


구조체를 캡슐화 했듯이, 함수들도 캡슐화해 줍니다.



이제, C/C++ 으로 작성한 코드를 C# 에서 사용할 수 있습니다.


끝.

브니 Programs/C++

01 14, 2007 02:17 01 14, 2007 02:17
[로그인][오픈아이디란?]
오픈아이디로만 댓글을 남길 수 있습니다