정보공간_1

[6기 강북 이보희] C++로 DLL 만들기 본문

IT 놀이터/Elite Member Tech & Talk

[6기 강북 이보희] C++로 DLL 만들기

알 수 없는 사용자 2014. 11. 24. 21:53

 안녕하세요. 강북멤버십 22-1기 이보희입니다.

 이번에는 C++에서 DLL을 만들고 C#에서 사용하는 방법, C++, C# 간 마샬링에 대해 알아보도록 하겠습니다. 먼저 C++에서 DLL을 만드는 방법 부터 살펴보겠습니다.


1. DLL 이란?

 DLL이란 동적 연결 라이브러리로 여러 함수의 공유 라이브러리로 사용되는 실행 파일입니다. 동적 링크를 사용하여 프로세스에서 해당 프로세스의 실행 코드에 포함되지 않은 함수를 호출할 수 있습니다. 함수의 실행 코드는 DLL에 있으며, DLL에는 이것을 사용하는 프로세스와는 별도로 컴파일, 링크 및 저장되는 하나 이상의 함수가 포함되어 있습니다. DLL을 사용하여 데이터와 리소스를 쉽게 공유할 수 있습니다. 즉, 여러 개의 응용 프로그램이 메모리에 있는 하나의 DLL 복사본 내용을 동시에 액세스 할 수 있습니다. 


 1) 정적 링크와의 차이?

 동적 링크는 DLL 함수의 실행 코드를 찾기 위해 런타임에 필요한 정보만을 실행모듈(.DLL 또는 .EXE 파일)에 포함한다는 점에서 정적 링크와 다릅니다. 정적 링크에서는 링커가 정적 연결 라이브러리에서 참조되는 모든 함수를 가져와서 코드와 함께 실행 파일 안에 포함시킵니다.

 정적 링크 대신 동적 링크를 사용하는 데에는 다음과 같은 몇 가지 장점이 있습니다.

 - 메모리 절약

 - 스와핑 감소

 - 디스크 공간 절약

 - 용이한 업그레이드

 - 출시 후 지원 제공

 - MFC 라이브러리 클래스를 확장할 수 있는 메커니즘 제공

 - 여러가지 언어 형식의 프로그램 지원

 - 용이한 국가별 버전 생성


 msdn에 따르면, 이런 라이브러리를 사용하면 코드를 매우 편리하게 다시 사용할 수 있습니다. 만드는 모든 프로그램에서 동일한 루틴을 다시 구현하는 대신 이러한 루틴을 다시 구현하는 대신 이러한 루틴을 한 번만 작성한 다음  해당 기능이 필요한 앱에서 이 루틴을 참조하게 한다고 되어 있습니다.

 DLL에 코드를 삽입하여 이 코드를 참조하는 모든 앱에서 공간을 절약하고 모든 앱을 다시 컴파일 할 필요 없이 DLL을 업데이트 할 수 있다고 합니다.

 

2) 응용 프로그램과 DLL의 차이?

 DLL과 응용 프로그램은 모두 실행 가능한 프로그램 모듈이지만 다른 점이 몇 가지 있습니다. 최종 사용자에게 있어 가장 분명한 차이점은 DLL의 경우 사용자가 직접 실행할 수 있는 프로그램이 아니라는 점입니다. 또한 시스템 관점에서 볼 때 응용 프로그램과 DLL 사이에는 다음과 같은 두 개의 기본적인 차이점이 있습니다.

- 응용 프로그램의 경우에는 시스템에서 해당 인스턴스가 동시에 여러 개 실행될 수 있지만 DLL의 경우에는 하나의 인스턴스만 실행됩니다.

- 응용 프로그램에는 스택, 전역 메모리, 파일 핸들 및 메시지 큐 등이 포함될 수 있지만 DLL은 그렇지 않습니다.


2. DLL 생성하기

아래 내용은 Visual Studio 2010을 기준으로 작성되었습니다.


1) 메뉴 모음에서 파일, 새로 만들기, 프로젝트를 차례로 선택합니다.


2) 설치된 템플릿의 Visual C++을 확장하고 Win32 콘솔 응용 프로그램을 선택하고 프로젝트 이름을 설정해 줍니다.


3) Win32 응용 프로그램 마법사 대화 상자의 개요 페이지에서 다음 단추를 선택하고 응용 프로그램 설정 페이지의 응용 프로그램 종류 아래에서 DLL을 선택합니다. 마침 단추를 선택하여 프로젝트를 만듭니다.


4) 간단하게 사칙 연산을 하는 함수를 만들어 보겠습니다.

extern "C" __declspec(dllexport) 

double Add(double a, double b)

{

return a+b;

}


extern "C" __declspec(dllexport) 

double Sub(double a, double b)

{

return a-b;

}


extern "C" __declspec(dllexport) 

double Mult(double a, double b)

{

return a*b;

}


extern "C" __declspec(dllexport) 

double Div(double a, double b)

{

return a/b;

}

일반 함수를 정의하는 방법과 동일하지만 함수 앞에 extern "C" __declspec(dllexport) 라는 키워드가 붙은 것을 볼 수 있습니다. 이 키워드가 DLL 만들기의 핵심으로, 함수의 선언과 정의 시에 이를 붙이지 않을 경우 DLL을 사용하는 다른 DLL이나 프로그램에서 해당 함수를 호출해서 사용할 수 없게 됩니다. (링크 과정에서 심볼 에러가 발생합니다.)


위 소스를 컴파일 하면 dll파일이 생성되는 것을 볼 수 있습니다.


5) DLL 사용하기

 생성한 DLL을 사용하는 프로그램을 만들도록 하겠습니다. 콘솔 응용 프로그램을 새로 만들고 테스트 소스를 아래와 같이 입력합니다.


#include "stdio.h"

#pragma comment(lib, "MakeDLL.lib")   

 // 위 구문은 lib 파일을 포함시키는 명령어 입니다. 컴파일된 라이브러리의 lib 파일을 해당 소스가 컴파일시에 컴파일러가 필요하기 때문입니다.


extern "C" __declspec(dllimport) double Sub(double a, double b);

// 위 구문은 dllimport 키워드를 사용해 위 함수가 dll에서 사용되는 함수라는 것을 명시해주는 것입니다. 

// DLL을 생성할 때는 dllexport 키워드를 사용했다면, DLL을 사용할 떄는 dllimport 키워드를 사용하게됩니다. dllexport 키워드는 꼭 명시해줘야 하는 반면에 dllimport 키워드는 필수 요소가 아닙니다. dllimport를 명시해줄 경우 컴파일 시 어셈블리 코드가 더 효율적으로 생성된다고 하니 선택해서 사용하시면 될 것 같습니다.


int main()

{

double result;


result = Sub(1.0, 4.0);

printf("%lf\n", result);


return 0;

}


 DLL 생성시 만들어진 라이브러리 파일(.dll, .lib)은 응용프로그램의 소스코드가 위치한 곳에 존재해야 정상적으로 컴파일 되므로 응용프로그램을 컴파일 하기 전에 복사해 주도록 합니다. 


 응용프로그램을 컴파일 한 후 실행시키면, 정상적인 결과가 출력되는것을 볼 수 있습니다. 


다음 글에서는 C#에서 dll을 사용하는 방법에 대해 알아보겠습니다.


참조문헌

 - http://msdn.microsoft.com/ko-kr/library/1ez7dh12.aspx