DLL 만들때 주의할 점

Serepha0921·2025년 5월 23일
post-thumbnail

Dll을 만들다 보면 c#앱에서 불러올때 여러 오류가 발생한다. 나중에 dll 오류가 날때를 대비해 대응방법과 만들때 주의할점을 기록한다. 아직 뉴비라 많이 부족합니다. 틀린 부분이나 고칠 부분이 있으면 알려주세요.

Dll 만들때 주의할 점


1. 함수 노출은 extern "C" + __declspec(dllexport) 조합

#pragma once
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
extern "C"{
	MYDLL_API bool MyFunction(char* buffer, int len);
}
  • extern "C"는 C++의 이름 맹글링을 막기 위해 필요, C#이나 다른언어에서 DLLImport로 함수로 호출이 가능해진다.

2. 프로젝트 빌드 대상은 X64 또는 X86으로 명확하게 지정

  • DLL 쓰는 앱이 x64면 DLL도 반드시 x64여야 한다.
  • AnyCpu로 빌드된 C#앱은 기본적으로 64비트 머신에서 x64로 실행된다
  • 하지만 visual studio 설정 또느 실행시 DLL를 쓸때 x86 버전을 쓸 수 있기 때문에 빌드 대상을 통일해라.

3. 헤더에 노출할 함수만 명시적으로 선언

  • 내부용 함수는 static이나 헤더가 아닌 .cpp파일 안에서 선언해 외부 노출을 막는다.

4. 데이터 교환시 마샬링을 고려해라

  • Char*은 C#에 없으니 C#에서는 StringBuilder를 사용해라.
  • C#의 bool과 C++의 bool은 비트수가 다르다.
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool mydll_function([Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, int bufferMaxLength);

5. SDK나 외부 라이브러리를 포함할 경우

  • .lib 파일과 .dll의 비트수가 일치해야한다.
  • 의존 dll도 실행 디렉토리에 모두 복사해야한다.
  • 의존 dll의 비트수가 다를 경우 오류가 난다.

오류 발생 시 대응


An attempt was made to load a program with an incorrect format. (0x8007000B)

  • 원인: 비트수 불일치
    ex) 앱 x64 vs dll:x86
  • 확인:
dumpbin /headers mydll.dll | findstr machine
  • Dependencies 툴로 모든 의존 dll 비트 수까지 검사해라. 그 중 하나가 비트 수가 다르면 오류가 난다.

DllNotFoundException
BadImageFormatException

  • 원인: dll이 실행 디렉토리에 없거나 의존 dll이 누락 되었거나 DLL로딩에 실패했는데 경로/포맷 오류일 수 있다.
  • 확인:
    • Dependencies: 의존 dll 모두 검사
    • ProcMon으로 실제로 로드되는 dll 경로 추적
    • 밑의 툴로 dll에서 실제로 함수들이 외부로 노출이 되는지 확인

      dumpbin /exports mydll.dll

AccessViolationException

  • 원인: c++함수와 c#선언이 일치 하지 않음
  • 확인: 함수와 변수 이름과 확인.
    • Ex) C#의 bool(4byte)과 C++(1byte)의 bool은 크기가 다르기 때문에 마샬링을 제대로 지정해야한다.

C++과 c#간 호환성


상황C++C#
문자열char*StringBuilder, [Out] + LPStr
문자열char[64][MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] string
boolbool[return: MarshalAs(UnmanagedType.I1)]
구조체struct[StructLayout(LayoutKind.Sequential)]
함수 호출__cdeclCallingConvention.Cdecl
함수 호출__stdcallCallingConvention.StdCall

도구


profile
안녕하세요. 뉴비 입니다

0개의 댓글