Building a DLL with Visual C++

Publish Date: Nov 30, 2018 | 197 Ratings | 4.11 out of 5 | Print | 22 Customer Reviews | Submit your review

Overview

Microsoft's Visual C++ (MSVC) integrated development environment (IDE) can be overwhelming if the programmer has never used it. This document is designed to aid those wanting to compile a DLL for use with LabVIEW.

Note: This document applies to MSVC 2010.

Table of Contents

  1. Step 1: Creating a DLL Project
  2. Step 2: Editing the Source File
  3. Step 3: Exporting Symbols
  4. Step 4: Specifying the Calling Convention
  5. Step 5: Building the DLL

1. Step 1: Creating a DLL Project

Select File»New Project to open the New Project dialog box. From the Visual C++ Templates list, select Win32 Project, name your project and click OK.



In the next dialog box, you may see the current project settings to be Windows Application. Click Next to change the Application Type to DLL.



MSVC creates a DLL project with one source (.cpp) file, which has the same name as the project. It also generates a stdafx.cpp file. The stdafx.cpp file is necessary, but you do not generally need to edit it.

 

Back to Top

2. Step 2: Editing the Source File

Every DLL file must have a DllMain function, which is the entry point for the library. Unless you must do a specific initialization of the library, the default DllMain that MSVC created is sufficient. Notice that this function does nothing.

BOOL APIENTRY DllMain( HANDLE hModule,
                        DWORD  ul_reason_for_call,
                        LPVOID lpReserved )
{
    return TRUE;
}

If a library initialization is required, you might need a more complete 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;
}

Once the DllMain function is complete, write the routines that you intend to access from the 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);
}

For the DLL to compile correctly, you must declare the pow function (i.e. power, pow(x,y) is equivalent to x^y) and the constant M_PI (i.e. 3.14159).
Do this by inserting two lines of code below #include "stdafx.h" at the top of the .cpp file. The code should look as follows:

#include "stdafx.h"
#include "math.h"    //library that defines the pow function
#define M_PI 3.14159 //declare our M_PI constant


At this point, you can compile and link the DLL. However, if you do so, the DLL will not export any functions, and thus, will not really be useful.

 

Back to Top

3. Step 3: Exporting Symbols

To access the functions within the DLL, it is necessary to tell the compiler to export the desired symbols. However, you first must address the issue of C++ name decoration. MSVC compiles your source as C++ if it has a .cpp or .cxx extension. If the source file has a .c extension, then MSVC compiles it as C. If you compile your file as C++, then the function names are normally decorated in the output code. This might be problematic because the function name has extra characters added to it. To avoid this problem, declare the function as 'extern "C"' in the function declaration, as follows:

extern "C" int GetSphereSAandVol(double radius, double* sa, double* vol);

This prevents the compiler from decorating the name with C++ decorations.

Warning: Without C++ decoration, polymorphic functions are not possible.


When you finish with the C++ decorations, you can actually export the functions. There are two methods to inform the linker which functions to export. The first, and most simple, is to use the __declspec(dllexport) tag in the function prototype for any function you want to export. To do this, add the tag to the declaration and definition, as follows:

extern "C" __declspec(dllexport) int GetSphereSAandVol(double radius, double* sa, double* vol);
...
__declspec(dllexport) int GetSphereSAandVol(double radius, double* sa, double* vol)
{
     ...
}

The second method is to use a .def file to explicitly declare which functions to export. The .def file is a text file that contains information the linker uses to decide what to export. It has the following format:

LIBRARY   <Name to use inside DLL>
DESCRIPTION "<Description>"
EXPORTS
    <First export>   @1
    <Second export>  @2
    <Third export>   @3
    ...

For the example DLL, the .def file will look like this:

LIBRARY   EasyDLL
DESCRIPTION "Does some sphere stuff."
EXPORTS  
    GetSphereSAandVol   @1

If you have properly created your DLL project, then the linker automatically looks for a .def file of the same name as the project in the project directory. To change this option, select Project»Properties. In the Linker folder, click the Input property page and modify the Module Definition File property to /DEF: <filename>.def .

See Also:
Microsoft's .DEF file method documentation

 

Back to Top

4. Step 4: Specifying the Calling Convention

The last thing that you might need to do before compiling the DLL is to specify the calling convention for the functions that you want to export. Usually, there are two choices: C calling convention or standard calling conventions, also called Pascal and WINAPI. Most DLL functions use standard calling conventions, but LabVIEW can call either.

To specify C calling conventions, you do not need to do anything. This is the default unless you specify otherwise in Project»Properties»C/C++»Advanced. If you want to explicitly declare the function as a C call, use the __cdecl keyword in the function declaration and definition:

extern "C" __declspec(dllexport) int __cdecl GetSphereSAandVol(double radius, double* sa, double* vol);
...
__declspec(dllexport) int __cdecl GetSphereSAandVol(doublt radius, double* sa, double* vol)
{
     ...
}

To specify standard calling conventions, place the __stdcall keyword in the function declaration and definition:

extern "C" int __stdcall GetSphereSAandVol(double radius, double* sa, double* vol);
...
int __stdcall GetSphereSAandVol(doublt radius, double* sa, double* vol)
{
     ...
}

When using standard calling conventions, the function name is decorated in the DLL. You can avoid this by using the .def file method of exporting functions, rather than the __declspec(dllexport) method. Therefore, National Instruments recommends that you use the .def file method to export stdcall functions.

 

Back to Top

5. Step 5: Building the DLL

Once you write the code, declare what functions to export, and set the calling conventions, you are ready to build your DLL. Select Build»Build <Your project> to compile and link your DLL. You are now ready to use or debug your DLL from LabVIEW. The attached EasyDLL.zip file contains the Visual C++ workspace used to create this DLL and a LabVIEW VI that accesses the DLL.

Back to Top

Customer Reviews
22 Reviews | Submit your review

q??  - Sep 16, 2010

ok thats good, but how i can call the function using *.cpp code? thqank you

  - Sep 8, 2010

Can I do the same but with Borland or C++ builder?, I've tried many times but without succes yet. Is not examples with these IDE's? Thanks

  - Jun 22, 2010

Anybody have the same example that include class definition? The following cod doesn't work for me: Header file: extern "C" class MyClass : public QObject { Q_OBJECT public: MyClass (); ~MyClass (); __declspec(dllexport) QString __cdecl OpenPort(); C++ file: __declspec(dllexport) QString __cdecl MyClass::OpenPort() Any Ideas?

Franck  - May 30, 2010

Thank you for the example. I am trying to create a DDL library using Visual Studio 2010, but have not been able to make it work. I can not find examples or tutorials for this C++ version and the available examples do not work with this version. Do you know where to find it? Thank you

  - May 29, 2010

Thanks for tutorial,it is great.I build dll file but now i want to test it using visual basic 6.0(to call this dll to a form in visual basic 6.0).Could you tell me the steps to do this?Please help me as soon as possible because i need a lot. Best regards. Thanks a lot again

  - Mar 17, 2010

It is useful for me,thanks!

  - Dec 27, 2008

Thank you very much. This article was indeed helpful. Thanks againks again

nice  - Oct 21, 2008

it really helped us to make a dll file

Very Useful Article for Beginner's  - Jul 7, 2008

Excellent++..none other esay way than this...If possible please make avoilable the article covering a dll intercommunication.

Very good, excellent...  - Dec 27, 2007

First I am looking for basic of dll. This tutorial is helpful for me in my project.

Good Tutorial.  - Dec 11, 2007

Tried doing it my own way just using this as a guide and flopped. Walked through your example and NOW I UNDERSTAND! Babystep1...2...

  - Jun 3, 2005

There are a few spelling mistakes that might throw people off (ie the first parameter in the second example of DLLMain ()). Otherwise great, straight forward tutorial. Next step: provide an example of a program USING the DLL that was made & it's functions.

  - Apr 18, 2005

Good, straight to the point, thanks

Excellent tutorial...  - Oct 31, 2004

Applies to VB6 as well. Must use standard calling conventions though...

  - Jun 5, 2004

Thanks for the good job. Great article.

After struggling on my own, this has given me the confidence to try again... :-)  - Oct 23, 2003

Haven't tried it yet, but this has answered so many of those 'but WHY??!?' questions that I'm about to try again.

  - Apr 23, 2003

The stuff is very cool. I suggest that you should add sample how to use the EasyDLL.dll in a program. I mean how to call the function inside the dll in a C++ program. Thanks a lot.

Thanks  - Mar 28, 2003

This helped me a lot. Thanks for sharing.

  - Nov 14, 2002

very good, easy to follow, made my first dll file and called it from LabVIEW successfully. didn't meet any problem, easier to understand than the example in the "Using External Code in LabVIEW" manual. Thanks

Small bug in GetVol  - Jul 12, 2001

In GetVol, the code "4/3" will evaluate as integer division (i.e. 4/3 equals 1). It should be "4./3." I guess Step 5 is correct, then, when it says, "Realistically speaking, you're now ready to debug your DLL." ;) Other than that, I agree with the comments from the other user. You should provide a complete project zip file or something that actually compiles. There are a couple hidden steps (#include <math.h>, for instance) that a true novice will be missing. Generally, though, these are good instructions.

Please provide a complete example, that executes.  - Jan 14, 2001

While this document is a good starting point, it would be a lot more efficient to provide a number of complete examples, of dlls that do something. This should include a complete "workspace", with all files, and the final dll that can be used, similar to the LabVIEW examples libraries. The average LabVIEW user may not be skilled in using a Visual C++ IDE, but with a more comprehensive set of examples, could accomplish quite a lot. To support my argument, from the user's point of view: 1.If I have to hire somebody else to do this for me, it may just lead to a lot of hassle and frustration - for a relatively simple task; such as generating a wrapper dll to pass data to another dll. 2.If I have to teach myself Visual C++ to do it... Well, the average LabVIEW user doesn't like that. Alternatively, select and point out more resources (examples, etc), to address this topic.

I could not get this aproach to work but I did find another way  - Aug 21, 2000

I may have got on of the stages wrong or not understood one of the finer points but I could not get a DLL made within Visual C++ to work within CVI. What I did was to to rebuild the .lib file within CVI. All I had to do was to open the .h from the DLL, select Options->Generate DLL Import Library and then select the DLL to be linked. It all worked fine after that

View more reviews

Bookmark & Share


Downloads

Attachments:

easydll.zip


Ratings

Rate this document

Answered Your Question?
Yes No

Submit