본문 바로가기
프로그래밍/프로그래밍

[C#] C로 작성된 Dll 사용하기

by 완소루피 2020. 10. 30.
728x90
반응형

C로 작성된 Dll을 C#에서 작업해야 하는 상황


우선 문제가 되는 것은 다음 사항이었다.
1. 어떻게 호출해서 사용하는가?
2. 포인터는 어떤게 전달하고 전달 받는가?

● 어떻게 호출해서 사용하는가?
C++로 작성된 Dll은 Standard 호출 방식으로 선언해 주어야 한다. <== 요게 포인터다.
(Dll 작성시 아주 중요한 부분이다. 체크)
extern "C" int __declspec(dllexport) Test(int a, void* b);

C#에서 함수를 호출해서 사용하는 방법과 클래스를 호출해서 사용하는 방법 2가지가 있다.
1. 함수를 호출하는 방법

[DllImport("test.dll")]

public static extern Test(int a, IntPtr b);

2. 클래스를 받아서 사용하는 방법
해당 부분에 대해서는 정확히 설명해 놓은 부분이 없어서 엄청 고생했다. ㅋㅋ
보통 PC는 네이티브 DLL 파일을 COM에 등록시킨 다음 C#에서 참조 추가하는 방법.
요 방법이 좀 까다롭다. 그래서 추천하는 방법은 다음과 같다.

- C++에서 이런 클래스가 DLL로 되어 있고 사용하고 있다면.

class TestClass

{

   public:
      TestClass(int);

      void foo(void);

      float bar(float);

}

- 다음과 같이 Export하는 함수를 만든다.
extern "C" TestClass* __declspec(dllexport) TestClass_Ctor(int v) { return new TestClass(v); }

- C#에서는 TestClass와 동일한 함수를 갖는 인터페이스를 만들고 Export 함수로 클래스의 객체 인스턴스를
 받아서 사용한다.
public interface TestClass

{

   void foo();

   float bar(float value);

}

public class Test
{
   [DllImport("test.dll")]
   public static extern TestClass TestClass_Ctor(int v);

}

static void Main(string[] args)
{
   TestClass tc = TestClass_Ctor(10);
}

 

------------------------------------------------------------------------------------------------------------------

3. Wrapper 클래스를 사용한 방법도 있습니다.
이 방법은 PC에서는 사용할 수 있으나, 스마트장치 개발환경에서는 지원하지 않는 사항입니다.
출처: http://kindtis.tistory.com/66

-엔진단을 정적 라이브러리로 작성한 후 이것을 C++/CLI(Managed C++)로 랩핑하여 Dll로 작성합니다.
그 다음 빌드된 Dll을 C# 프로젝트에서 참조 추가한 후 사용하면 되는 식입니다.
즉, 사용하고자 하는 C++ 엔진 부분은 정적 라이브러리로 작성을 하고 C++에서 랩핑 프로젝트를
추가하여 Dll을 만든다. 이때 [프로젝트 속서]-[일반]-[공용 언어 런타임 지원]을 선택하여 만든다.

(Tip)
윈도우 자체 핸들을 받아서 Drawing 작업하면 화면에 못 그립니다.
     대신 윈도우에 PictureBox 컨트롤을 만들어두고 그 PictureBox 컨트롤의 핸들을 넘겨줍니다. 그 화면에
     그리면 됩니다.


● 포인터는 어떤게 전달하고 전달 받는가?

1.  C++ 로 만든 Dll에서의 정의 부분
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;

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);

2. C# 호출부 작성 코드
C/C++ DLL 을 참조하기 위해  [C# 프로젝트의 속성] - [빌드 이벤트] - [빌드 후 이벤트 명령줄] 에 다음을 추가합니다.

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

C/C++ DLL 파일을 C# 프로젝트의 출력 디렉토리로 복사해 오는 것입니다.

이를 위해서 프로젝트 '종속성'에 'BND.Native' 프로젝트를 추가해야 합니다.

- 구조체 캡슐화

    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();

        // 구조체를 초기화하는 코드를 생성자 내부에 작성합니다.

 

- 함수 참조 선언

         // 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);

  

- 함수 캡슐화

         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;

        }

 

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

728x90
반응형

'프로그래밍 > 프로그래밍' 카테고리의 다른 글

[ADB] Airplane Mode 변경  (0) 2020.11.12
c# 다중언어  (0) 2020.11.02
버블정렬  (0) 2018.03.22
C++로 간단한 퀴즈 프로그램 만들기  (0) 2018.03.22