visual studio 2017 에서 dll 만들기 컴퓨터


시작하기에 앞서 폴더구조를 보이면.

솔루션의 이름이 M 드라이버 밑의 DLL 
DLL 만드는 프로젝트 이름이 create
만든 dll 파일을 사용하는 프로젝트 이름이 enjoy
솔루션의 결과물이 담기는 곳이 Debug다

하나의 솔루션 밑에 두개의 프로젝트가 있다.

아래 그림과 같다.





dll.h 파일의 내용이다.

#ifdef CREATE_EXPORTS
#define MYDLL __declspec(dllexport)
#else
#define MYDLL __declspec(dllimport)
#endif

MYDLL int add(int x, int y);


#ifdef 문이다.

CREATE_EXPORTS가 정의되어 있으면 

    MYDLL 이  __declspec(dllexport) 가 되고

그렇지 않으면 

    MYDLL 이  __declspec(dllimport) 가 된다.


VS 에서는 프로젝트가 DLL 형식이면 컴파일되면서 

프로젝트이름(대문자)_EXPORTS

가 자동적으로 정의된다.

여기서는 프로젝트이름이 create 이니까 대문자로 바뀌어 

CREATE_EXPORTS 가 정의된다.

그래서 create프로젝트를 컴파일할때 

MYDLL은 __declspec(dllexport) 로 바뀐다.

이 헤더파일은 여기서도 쓰이지만 나중에 만들어 볼 dll 을 사용하는 프로젝트에서도 사용된다. 그곳에서 사용될때는 

MYDLL 이 __deslspec(dllimport) 로 바뀐다. 

왜냐하면 그 프로젝트를 컴파일할 때 CREATE_EXPORTS가 정의될 리가 없기 때문이다.
프로젝트 이름도 create가 아닐 뿐더러 dll을 만들지도 않기에 당연한 소리다.

DLL 안에 있는 함수를  DLL 밖에서 사용할때는 함수선언할 때 dllimport 가 붙고 

DLL 안에 있는 함수를  밖에서 사용하게 할때는 함수선언할 때 dllexport 가 붙는다.

어떤 dll 파일속에 add 함수가 있고 그걸 밖에서 쓸 수 있게 할려면 

int add(int x, int y)  을 

__deslspec(dllexport) int add(int x, int y)

이렇게 하며,

어떤 dll 밖에서 add 함수를 쓰려면 

__declspec(dllimport) int add(int x, int y) 

이렇게 해줘야된다.


이제 본문.

create.cpp 에 다음과 같이 적는다.

#include "stdafx.h"
#include "dll.h"

int add(int x, int y){
return x + y;
}

글자수로만 따지면 본문이 헤더보다 적다. 간단하게 하려고 해서 그런거지 하염없이 늘어날수 있는곳이다.


이제 빌드만하면 dll파일이 만들어진다. 솔루션 빌드를 사용한다.

처음에 보여줬던 Debug폴더가 만들어지며 그 곳에 create.dll 파일이 만들어진다. 
탐색기에서 본 그림이다.



이제 사용하는 프로젝트를 이 솔루션안에 만든다.

처음에 했듯이 

파일 > 새로 만들기 > 프로젝트 > Visual C++ > Win32 콘솔

프로젝트 이름은 enjoy 
위치는 m:\
솔루션이름은 <만들기> 가 아니라 <솔루션에 추가>를 선택한다. 옆의 콤보버턴을 누르면 그 메뉴가 나온다.




DLL 솔루션 밑에 enjoy 프로젝트가 나타났다.


새로 만든 enjoy 프로젝트에서 같은 솔루션에 있는 create프로젝트를 알게해야 한다. 두가지를 해줘야한다.

하나는 참조. 또하나는 dll.h 파일이 있는곳의 폴더추가

먼저 참조부터.

enjoy 프로젝트 > 참조 > 참조추가 

대화상자에서 create 옆의 체크박스를 체크한다.




create 프로젝트를 선택한다.


참조는 끝났고 이제는 폴더추가 

create 폴더를 추가한다. 그 곳에 dll.h 파일이 있다.

enjoy 프로젝트선택 > 프로젝트 > 속성 > 구성 속성 > C/C++ > 일반 > 추가 포함 디렉토리

에서 create 폴더의 위치를 지정한다.

현재 있는 곳이 enjoy 폴더이니까 상대경로로 

..\create 

라고 적을 수도 있고. 여기서는 이렇게 적었다.

m:\DLL\create 

이렇게 절대경로를 적을 수도 있다.


enjoy.cpp 에서 다음과 같이 작성한다.

#include "stdafx.h"
#include "dll.h"
#include <stdio.h>

int main()
{
printf("2 + 3 = %d", add(2, 3));
return 0;
}

헤더추가했고 printf 문장하나다.

create.dll 속에 있는 add 함수를 사용했다.

솔루션 빌드한다.

빌드 > 솔루션 빌드

enjoy.exe가 만들어졌다.






enjoy.exe 를 더블클릭하면 뭔가가 번쩍 나타나고 바로 사라진다.

cmd 창에서 실행하면 이렇게 보인다.

vs에서 실행하려면 enjoy 프로젝트를 시작 프로젝트로 지정해 줘야한다.

따로 건드리지 않았다면 처음 만든 create프로젝트가 시작프로젝트로 지정되어있다. 솔루션 탐색기상에서 create 가 enjoy 보다 글자색이 진한데 그게 시작프로젝트를 나타낸다. 

디버거 > 디버거하지 않고 시작

이렇게 해보면 에러메시자가 나온다.


enjoy 프로젝트를 선택 > 프로젝트 > 시작프로젝트로 설정


다시 해보면 

디버거 > 디버거하지 않고 시작

아래와 같이 나타난다.


끝.

하나만 더..

이건 읽으면 좋고 안읽어도 그만인 내용이다.

create.dll 의 pe헤더를 살펴보면 함수 add의 이름이 요상하게 나타난다. 

혹시라도 이 dll을 다른곳에서도 사용할려면 이런 이름을 가지고는 이 함수를 사용하기는 어렵다. 

GetProcAddress(hInstance,"?add@@YAHHH@Z");

복잡해보이기도 하지만 틀리기도 쉽다.

헤더파일에 한줄을 추가하면 이런 문제가 없어진다. 즉,

extern "C" 

를 추가한다.

//dll.h

#ifdef EXIM
#define MYDLL __declspec(dllexport)
#else
#define MYDLL __declspec(dllimport)
#endif

extern "C"

MYDLL int add(int x, int y);

이렇게 해서 만들면 함수이름이 본래대로 나타난다.


이제 다른곳에서 

GetProcAddress(hInstance,"add");

이렇게 정상적으로 사용할 수 있다.


덧글

  • karlcom 2018/03/23 16:57 # 삭제 답글

    상세한 설명 감사합니다.
  • 공인 2018/07/01 00:34 # 삭제 답글

    많은 도움 되었습니다.
  • 이힛 2018/07/17 15:06 # 삭제 답글

    2017에서 만드는 방법이 궁금했는데 덕분에 해결했네요 고맙습니다.
  • 오호 2019/03/22 02:12 # 삭제 답글

    두시간 동안 헤맨 dll을 드디어 해결 했습니다. 정말 감사합니다.
댓글 입력 영역