DLL 프로젝트 생성하기
Microsoft 튜토리얼의 단계에 따라 C ++ DLL을 만듭니다.
Walkthrough: Create and use your own Dynamic Link Library (C++)
- Visual Studio에서 File » New Project를 선택하여 새 프로젝트 대화 상자를 엽니다. Visual C++ 템플릿 목록에서 Win32 Project를 선택하고 프로젝트 이름을 지정한 다음 확인(OK)을 클릭 합니다.
- 다음 대화 상자에서 현재 프로젝트 설정이 Windows application 인 것을 볼 수 있습니다. 다음(Next)을 클릭하여 응용 프로그램 유형을 DLL로 변경합니다.
- 마침(Finish)을 선택하여 DLL을 만듭니다. MSVC는 프로젝트와 이름이 같은 하나의 소스 (.cpp) 파일로 DLL 프로젝트를 만듭니다. stdafx.cpp 파일도 생성합니다. stdafx.cpp 파일이 필요하지만 일반적으로 편집할 필요는 없습니다.
소스 파일 편집
- 모든 DLL 파일은 라이브러리의 진입점으로의 DllMain 함수가 있어야합니다. 요구와 필요 기능에 따라서 당신의 DllMain 함수를 편집할 수 있습니다.
- 라이브러리의 특정 초기화를 수행해야하는 경우가 아니면 MSVC가 만든 기본 DllMain 이면 충분합니다. 이 함수는 아무 작업도 수행하지 않습니다.
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
return TRUE;
}
- 라이브러리 초기화가 필요한 경우 DllMain 을 수정합니다.
BOOL WINAPI DllMain(
HINSTANCEhinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE;
}
- DllMain 함수가 완료되면 DLL에서 액세스하는 루틴을 작성하십시오. 예를 들면 아래와 같습니다.
//Function declarations
int GetSphereSAandVol(double radius, double* sa, double* vol);
double GetSA(double radius);
double GetVol(double radius);
...
int GetSphereSAandVol(double radius, double* sa, double* vol)
//Calculate the surface area and volume of a sphere with given radius
{
if(radius < 0)
return false; //return false (0) if radius is negative
*sa = GetSA(radius);
*vol = GetVol(radius);
return true;
}
double GetSA(double radius)
{
return 4 * M_PI * radius * radius;
}
double GetVol(double radius)
{
return 4.0/3.0 * M_PI * pow(radius, 3.0);
}
- DLL이 올바르게 컴파일 되려면 pow 함수 (예: power, pow(x,y) 는 x ^ y와 동일)와 상수 M_PI (예: 3.14159)를 선언해야합니다. .cpp 파일의 맨 위에 #include "stdafx.h" 아래에 두 줄의 코드를 삽입하면됩니다. 코드는 다음과 같아야합니다.
#include "stdafx.h"
#include "math.h" //library that defines the pow function
#define M_PI 3.14159 //declare our M_PI constant
이 시점에서 DLL을 컴파일하고 연결할 수 있습니다. 그러나 그렇게하면 DLL은 값을 내보내지 않으므로 실제로는 아직 유용하지 않습니다.
심볼 내보내기
DLL 내의 함수에 액세스하려면 원하는 심볼을 내보내도록 컴파일러에 지시해야합니다. 그러나 먼저 C++ 이름 데코레이션(decoration) 문제를 해결해야합니다. MSVC는 소스에 .
cpp 또는 .
cxx 확장자를 사용하면, 이를 C++로 컴파일합니다. 소스 파일에 .
c 확장자를 사용하면 MSVC는 C로 컴파일 합니다. 파일을 C ++로 컴파일하면 데코레이팅 함수 이름이 일반적으로 출력 코드에 표시됩니다. 함수 이름에 추가 문자가 있는 경우에는 문제가 될 수 있습니다. 이 문제를 방지하려면 다음과 같이 함수 선언에서 함수를 'extern "C"'로 선언합니다.
extern "C" int GetSphereSAandVol(double radius, double* sa, double* vol);
이렇게하면 컴파일러가 이름을 C++ 데코레이션으로 변경하는 것을 막을 수 있습니다.
경고: C++ 데코레이션이 아니면 다형성 함수로 만들기는 불가능합니다.
C++ 데코레이션을 마치면 실제로 함수를 내보낼 수 있습니다. 내보낼 함수를 링커에 알리는 두 가지 방법이 있습니다. 첫 번째이자 가장 간단한 방법은 내보낼 함수에 대해 함수 프로토 타입에서 __declspec(dllexport) 태그를 사용하는 것입니다. 이렇게하려면 다음과 같이 선언 및 정의에 태그를 추가합니다.
extern "C" __declspec(dllexport) int GetSphereSAandVol(double radius, double* sa, double* vol);
...
__declspec(dllexport) int GetSphereSAandVol(double radius, double* sa, double* vol)
{
...
}
두 번째 방법은 .def 파일을 사용하여 내보낼 함수를 명시적으로 선언합니다. .def 파일은 링커가 내보낼 항목을 결정하는데 사용하는 정보가 포함된 텍스트 파일입니다. 형식은 다음과 같습니다.
LIBRARY <Name to use inside DLL>
DESCRIPTION "<Description>"
EXPORTS
<First export> @1
<Second export> @2
<Third export> @3
...
예제 DLL의 경우. def 파일은 다음과 같습니다.
LIBRARY EasyDLL
DESCRIPTION "Does some sphere stuff."
EXPORTS
GetSphereSAandVol @1
DLL 프로젝트를 제대로 만든 경우 링커는 자동으로 프로젝트 디렉토리에있는 프로젝트와 동일한 이름의 def 파일을 찾습니다. 이 옵션을 변경하려면 Project » Properties를 선택합니다. Linker 폴더에서 Input 속성 페이지를 클릭하고 Module Definition File 속성을 /DEF: <filename>.def로 수정 합니다.
또한 Microsoft의 Exporting from a DLL Using DEF Files 문서를 참조하십시오.
호출 규칙 지정
DLL을 컴파일하기 전에 해야 할 마지막 작업은 내보낼 함수에 대한 호출 규칙을 지정하는 것입니다. 일반적으로 C 호출 규칙 또는 Pascal 및 WINAPI라고도 하는 표준 호출 규칙의 두 가지 선택이 있습니다. 대부분의 DLL 함수는 표준 호출 규칙을 사용하지만 LabVIEW는 두가지 방법 모두로 호출 할 수 있습니다.
C 호출 규칙을 지정하기 위해 아무것도 할 필요가 없습니다.
Project » Properties » C/C++ » Advanced에서 달리 지정하지 않는 한 기본값입니다. 함수를 C 호출로 명시적으로 선언하려면 함수 선언 및 정의에
__cdecl 키워드를 사용하십시오.
extern "C" __declspec(dllexport) int __cdecl GetSphereSAandVol(double radius, double* sa, double* vol);
...
__declspec(dllexport) int __cdecl GetSphereSAandVol(doublt radius, double* sa, double* vol)
{
...
}표준 호출 규칙을 지정하려면 함수 선언 및 정의에
__stdcall 키워드를 배치합니다.
extern "C" int __stdcall GetSphereSAandVol(double radius, double* sa, double* vol);
...
int __stdcall GetSphereSAandVol(doublt radius, double* sa, double* vol)
{
...
}
표준 호출 규칙을 사용할 때 함수 이름은 DLL로 데코레이팅됩니다. __declspec (dllexport) 메소드가 아닌 함수를 내보내는 .def 파일 메소드를 사용하여 이를 방지 할 수 있습니다. 따라서 NI는 stdcall 함수를 내보내는 방법으로 .def 파일 메소드를 사용하기를 권장합니다.
DLL 빌드
코드를 작성하고 내보낼 함수를 선언하고 호출 규칙을 설정하면 DLL을 빌드할 준비가 된 것입니다. Build » Build <프로젝트명> 를 선택하여 DLL을 컴파일하고 연결합니다. 이제 LabVIEW에서 DLL을 사용하거나 디버그할 준비가 되었습니다. 첨부 된 EasyDLL.zip 파일에는 이 DLL을 생성하는데 사용되는 Visual C++ 워크스페이스와 DLL에 액세스하는 LabVIEW VI가 포함되어 있습니다.