LabVIEW에서 사용을 위해 Microsoft Visual C ++로 DLL 빌드

업데이트 됨 Mar 31, 2021

환경

소프트웨어

  • LabVIEW

다른

  • Microsoft Visual Studio

처음 Microsoft의 Visual C ++ (MSVC) 통합 개발 환경(IDE)을 사용하면 어려운 툴일 수 있습니다. 이 문서는 LabVIEW와 함께 사용하기 위해 DLL을 컴파일하려는 사용자를 돕기 위해 작성되었습니다.

참고: 이 문서는 MSVC 2010을 사용하여 작성되었습니다.

DLL 프로젝트 생성하기

Microsoft 튜토리얼의 단계에 따라 C ++ DLL을 만듭니다.  Walkthrough: Create and use your own Dynamic Link Library (C++)
  1. Visual Studio에서 File » New Project를 선택하여 새 프로젝트 대화 상자를 엽니다. Visual C++ 템플릿 목록에서 Win32 Project를 선택하고 프로젝트 이름을 지정한 다음 확인(OK)을 클릭 합니다.
  1. 다음 대화 상자에서 현재 프로젝트 설정이 Windows application 인 것을 볼 수 있습니다. 다음(Next)을 클릭하여 응용 프로그램 유형을 DLL로 변경합니다.


  1. 마침(Finish)을 선택하여 DLL을 만듭니다. MSVC는 프로젝트와 이름이 같은 하나의 소스 (.cpp) 파일로 DLL 프로젝트를 만듭니다. stdafx.cpp 파일도 생성합니다. stdafx.cpp 파일이 필요하지만 일반적으로 편집할 필요는 없습니다.

소스 파일 편집

  1. 모든 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;
}

 
  1. 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);
}

 
  1. 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가 포함되어 있습니다.

다음 단계

Attachments