logo MSJO.kr

C# Interop with C/C++

2019-10-15
MsJ
 

Native C/C++의 DLL을 C#에서 호출하여 사용하는 간단한 예제이다. 사용환경은 Visual Studio 2019, .NET Core 3.0을 선택하였고 모두 64bit로 빌드하였다. 주의할 점은 C++, C# 모두 x64이거나 x86으로 같이 맞추어야 에러가 나지 않는다.

C++ 64bit dll 프로젝트 생성
  1. 새 프로젝트 추가 : 언어 : C++
  2. Windows 데스크톱 마법사 → 프로젝트 이름 : Project1(임의)
  3. 애플리케이션 종류 : 동적 연결라이브러리(.dll)
C++ 64bit dll 프로젝트 설정
  1. 솔루션 탐색기 → 프로젝트 우측버튼 : 속성 선택
  2. 플랫폼 : x64
  3. C/C++ → 고급 → 호출규칙 : __stdcall(/Gz)

C++ 예제의 함수는 숫자를 반환하는 Add, 문자열을 반환하는 TestString 두 개고 작성 후 C#(.NET Core) 콘솔 프로그램에서 호출하여 사용한다. 아래는 전체 소스이다. 참고로 Project1.dll 파일은 C# 프로젝트의 실행 파일이 있는 곳에 복사한다.

전체 소스
// 기본 생성된 dllmain.cpp 하단에 아래와 같이 작성한다.
#include "pch.h"
#include <atlconv.h>
#include <stdio.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

// 추가로 작성한 부분
extern "C" __declspec(dllexport) int Add(int a, int b)
{
    return a + b;
}

extern "C" __declspec(dllexport) char* TestString(char* input)
{
    int x = 123;
    char test1[256];
    sprintf_s(test1,"헬로우 : %d : ", x);
    strcat_s(test1, input);
    size_t stSize = strlen(test1) + sizeof(char);
    char* pszReturn = NULL;
    pszReturn = (char*)::CoTaskMemAlloc(stSize);
    strcpy_s(_Post_ _Notnull_ pszReturn, stSize, test1);
    return pszReturn;
}
// Program.cs 콘솔
using System;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine(ImportTest.Add(3, 4));
            Console.WriteLine(ImportTest.TestString("가나닭"));
            /* 결과 
             7
             헬로우: 123 : 가나닭
            */
        }
    }

    public static class ImportTest
    {
        [DllImport("Project1.dll", EntryPoint = "Add", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int Add(int a, int b);

        [DllImport("Project1.dll", EntryPoint = "TestString", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.LPStr)]
        public static extern string TestString(string input);
    }
}

Prεv   Nεxt
Content
Search     RSS Feed     BY-NC-ND