동적라이브러리 (DLL) 만들기
1. 프로젝트 생성
Visual Studio → New Project → Win32 Project → Project, Solution name : DLibrary → OK
2. Header 파일
#pragma once |
2.1. 코드 분석
[ #ifdef 문 ]
MAKE_DLL_TEST_EXPORTS가 정의되어 있으면
DLLTEST 가 __declspec(dllexport) 가 되고
그렇지 않으면
DLLTEST 가 __declspec(dllimport) 가 된다.
즉 dll을 만들때는 dll 프로젝트 명과 동일하여 export 되고
dll 을 적용할 때는 import 가 된다.
[ __declspec(dllexport) 란? ]
__declspec은 함수의 특성을 지정하는 구문
dllexport용 함수라는 특성을 선언한다는 뜻
3. 소스 파일
#include <iostream> #include "make_dll_test.h" extern "C" DLLTEST_API int dll_test_sum(int a, int b) { return a + b; } extern "C" DLLTEST_API int dll_test_sub(int a, int b) { return a - b; } |
4. 빌드하면 정적라이브러리 (lib), 동적라이브러리 (dll) 생성됨
dll 과 lib
[dll 이란?]
dll = 동적 라이브러리
실행 파일에서 해당 라이브러리의 기능을 사용 시에만,
라이브러리 파일을 참조하여(혹은 다운로드받아) 기능을 호출함.
즉 프로그램이 실행 되었을 때 메모리에 적재 되어서
언제든지 이 라이브러리가 제공하는 함수에 대해 접근하고 사용할 수 있게 됨.
[lib란?]
lib = 정적 라이브러리
일반적으로 실행 파일을 만들 때는 소스 코드를 컴파일하고 만들어진 obj 파일을
링커가 하나로 묶어 exe 파일을 만듬
여기서 lib을 사용하면 링크 단계에서 링커가 이 lib파일도 같이 묶어서 하나의 exe 파일을 만듬
즉 빌드하여 만들어지는 exe 파일에 lib 내용이 모두 들어감
외부코드를 사용하기 위한 library로
dll = Runtime 중에
lib = Complie 할때 필요함
묵시적 (암시적 Implicit) 연결 방법
1. (lib 파일 인식) 프로젝트 우클릭 속성 -> 구성 속성 -> 링커 -> 일반 -> 추가라이브러리 디렉터리
생성한 lib 파일의 위치를 추가
2. (lib 파일 인식) 프로젝트 우클릭 속성 -> 구성 속성 -> 링커 -> 입력 -> 추가 종속성
생성한 lib 파일의 이름을 추가
3. (header 파일 인식) 프로젝트 우클릭 속성 -> 구성 속성 -> C/C++ -> 일반 -> 추가 포함 디렉터리
dll 만들때 사용했던 header 파일의 경로를 넣어줌
4. (dll 파일 인식)프로젝트 우클릭 속성 -> 구성 속성 -> 디버깅 -> 환경
dll파일이 있는 폴더 경로를 환경변수로 넣어줌
예 : PATH=%PATH%;D:\동적라이브러리_Test\dll_lib_header
참고 : 간단한 방법으로는 dll 을 프로젝트가 있는 폴더에 넣어주면 자동으로 인식함
5. dll 적용 예제 코드
#include <iostream> |
6. 코드 추가 설명
위 코드는 Header 파일에
extern "C" DLLTEST_API int dll_test_sum(int , int );
extern "C" DLLTEST_API int dll_test_sub(int , int );
가 명시되어 있어서 cpp 파일에 명시를 안했지만
header 에 명시하지 않은 경우
cpp 파일에
extern "C" DLLTEST_API int dll_test_sum(int , int );
extern "C" DLLTEST_API int dll_test_sub(int , int );
를 명시하면 사용할 수 있음
명시적 연결 방법
명시적 연결을 사용하면 필요할 때 dll 에서 함수를 로드하여
특정 함수 포인터에 사용하려는 함수를
맵핑시켜서 사용할 수 있음
1. (dll 파일 인식)프로젝트 우클릭 속성 -> 구성 속성 -> 디버깅 -> 환경
명시적 연결 방법은 DLL 만 환경변수로 바라보면 가능함
dll파일이 있는 폴더 경로를 환경변수로 넣어줌
예 : PATH=%PATH%;D:\동적라이브러리_Test\dll_lib_header
참고 : 간단한 방법으로는 dll 을 프로젝트가 있는 폴더에 넣어주면 자동으로 인식함
2. 예제 코드
#include <iostream> #include <windows.h> typedef int(*pDLLFunction)(int, int); pDLLFunction pFunction = NULL;
int main() { int a = 5; int b = 3; int c, d; HMODULE hMod = NULL; hMod = LoadLibraryA("make_dll_test.dll"); if (hMod == NULL) { printf("DLL Load Failed.\n"); return 0; } pFunction = (pDLLFunction)GetProcAddress(hMod, "dll_test_sum"); c = pFunction(a, b); pFunction = (pDLLFunction)GetProcAddress(hMod, "dll_test_sub"); d = pFunction(a, b); printf("a + b = %d\n", c); printf("a - b = %d\n", d); return 0; } |
3. 코드 설명
[ 1 ]
typedef int(*pDLLFunction)(int, int); |
pDLLFunction이라는 함수 포인터 자료형을 선언하고,
pFunction이라는 함수 포인터를 만들고, 이를 NULL로 초기화.
이 pFunction이라는 함수 포인터에 외부 DLL의 함수를 맵핑
[ 2 ]
HMODULE hMod = NULL; |
[ HMODULE 설명 ]
dll를 담아둘 수 있는 자료형
hMod 를선언하고 정의한 뒤에
상위에서 만들어두었던 make_dll_test.dll을 불러들임
이 때 사용되는 함수가 LoadLibraryA()라는 함수임.
이 함수는 dll파일을 불러들이지 못하는 경우 NULL을 리턴하며,
이 경우에 대한 예외처리를 해주어야함
dll파일이 불러들여졌다면
해당 dll파일에서 우리가 호출하고자 하는 함수를 불러들여야함
상위 DLL 만들기 프로젝트에서 만들어 두었던dll_test_sub 와dll_test_sum함수를 불러와야함
[ HMODULE 관련 오류 정리 ]
DLL 관련 오류
- 해당 DLL 라이브러리가 물고있는 DLL도 있어야 정상적으로 인식함
193 error
- 1) 라이브러리는 봤지만 해당 라이브러리 Bits 가 맞지 않음,
- 2) 해당 라이브러리와 연동되어있는 다른 dll 을 인식하지 못해서 오류발행
- 해결책 = 프로그램이 실행되는 경로에 dll 을 모두 같이 넣어줘야함
126 erro
- 라이브러리 경로 자체를 찾기 못한상황
- 해결책 = 라이브러리 경로를 다시 확인
[ 3 ]
pFunction = (pDLLFunction)GetProcAddress(hMod, "dll_test_sum"); |
pFunction에 pDLLFunction타입의 함수인 dll_test_sum 이름의 함수를 hMod라는 dll로부터 불러들인다는 뜻
함수명은 GetProcAddress 를 통해 매칭시킴
pFunction 함수에 dll_test_sum이 함수를 통해 a, b를 넘겨 리턴되는 값을 받음
'코딩 > C and C++' 카테고리의 다른 글
C++ windows 로컬 그룹 정책 확인 (1) | 2021.12.22 |
---|---|
C++ Windows console 결과 영어로 출력 (0) | 2021.12.22 |
네임드 파이프 (Named-Pipe) (1) | 2020.10.04 |
C++에서 JSON 사용 (4) | 2020.09.13 |
JSON (0) | 2020.09.13 |