manski's blog

Projects in Visual C++ 2010 – Part 1: Creating a DLL project

When you write software, you often/sometimes divide your project into several subprojects. This mini series describes how to do this with Visual C++ 2010 (but this first part also applies to earlier versions). We start with creating a library project in form of a DLL.

Related articles:

Library Projects

Library projects are projects that usually contain reusable functions or classes. They’re a great way of structuring a big project. In Visual C++ (or in C++ in general) there are two types of libraries: static libraries and dynamic libraries.

Static libraries (.lib) are “merged” into the final .exe file when the whole project is compiled. Therefore, for the outside user, this library type isn’t visible.

Dynamic libraries (.dll) on the other hand remain separate from the final .exe file in their own files. (See more information here.)

In this article we’ll create a dynamic library.

Creating the Library Project

To create a library project in Visual C++ 2010 (that is a part of Visual Studio 2010) in an existing solution, choose Add –> New Project... from the solution’s context menu in the “Solution Explorer” window.

Adding a new project by using the context menu

Alternatively you can create a new solution by using File –> New –> Project.... Either way will open up the “Add New Project” dialog. Here you choose “Class Library” (in section Other Languages –> Visual C++) and specify a new for the project. This name will also be the name of the DLL file.

Creating a new class library

After hitting “Ok”, your new class library project will be created. By default, it’ll create a dynamic library. To verify this, head to the project’s settings (available through the project’s context menu) and check that Configuration Type is set to Dynamic Library (.dll).

A static library project with CLR support disabled

You may also want to review the setting Common Language Runtime Support. If enabled (switch /clr), this will allow you to create .NET classes in this project. For a pure C++ project, however, you may want to disable CLR support (as shown in the screenshot above).

Writing a Reusable Class

The purpose of a library is to provide (potentially) reusable functions and/or classes. So, let’s create a simple reusable class.

The new class is called PrintableInt. It wraps an integer and provides a toString() method that will convert the integer into a string.

// PrintableInt.h
#pragma once

#include <string>

class PrintableInt
{
public:
  // Constructor
  PrintableInt(int value);
  // Converts the int into a string.
  std::string toString() const;
private:
  int m_value;
};
// PrintableInt.cpp
#include "stdafx.h"
#include "PrintableInt.h"
#include <sstream>

PrintableInt::PrintableInt(int value)
{
  m_value = value;
}

std::string PrintableInt::toString() const
{
  std::ostringstream builder;
  builder << m_value;
  return builder.str();
}

The library should now compile without problems.

Note that the .cpp file include a file called stdafx.h. This is a so called “precompiled header file”. This feature is explained in another article. It should, however, work out-of-the-box in your project.

Exporting Classes

By default, all classes and functions defined in a library project are “internal”. That means that another project can’t use them. To change this, classes (or function) that are to be used by other project must be “exported”. In Visual C++ you do this with __declspec(dllexport).

Now, you could specify the export like this:

// PrintableInt.h
class __declspec(dllexport) PrintableInt
{
  ...
}

However, since all projects using this library will most likely use the same header file (PrintableInt.h), this would mean that even the “using” projects would export the class as well. Of course, this is not what we want. Instead you create a macro and use it like this:

// PrintableInt.h

#ifdef COMPILE_MYLIBRARY
  #define MYLIBRARY_EXPORT __declspec(dllexport)
#else
  #define MYLIBRARY_EXPORT __declspec(dllimport)
#endif

class MYLIBRARY_EXPORT PrintableInt
{
  ...
}

For this to work, you add the preprocessor definition COMPILE_MYLIBRARY to the library project (but not to the projects using the library). This way MYLIBRARY_EXPORT will be replaced by __declspec(dllexport) when compiling the library project and by __declspec(dllimport) when using the project (from another project). To specify this preprocessor, go to the library project’s settings and enter the name COMPILE_MYLIBRARY in the field “Preprocessor Definitions”. You should also make sure to select “All Configuration” from the “Configuration” dropdown field (see screenshot) so that this definition gets added to the Debug and Release configuration.

Specifying a preprocessor definition

Note: The keyword __declspec(...) is a Microsoft specific extension to C++ (see here). So it only works in Visual C++. There is an alternative (more portable?) way to specify which classes/functions are to be exported. For this, a “Module-Definition File” (.def) needs to be created. However, creating such a file is more tedious than specifying the export statement directly in the code. For more information, see this article.

Now, when you compile the library project, an additional .lib file will be created. This file is used to import the exported classes/functions in another project. (If you don’t export anything, the file won’t be created.) How to do this, is explained in part two of this mini series.

dllimport necessary?

The example above specifies that __declspec(dllimport) is to be used when using the library project. You may notice that this isn’t necessary in the above example. However, it doesn’t hurt either.

This statement becomes important though when you export templated classes. To demonstrate this, change PrintableInt like this:

// PrintableInt.h
#pragma once

#include <string>

#ifdef COMPILE_MYLIBRARY
  #define MYLIBRARY_EXPORT __declspec(dllexport)
#else
  #define MYLIBRARY_EXPORT //__declspec(dllimport)
#endif

template<int T>
class MYLIBRARY_EXPORT PrintableInt
{
public:
  // Constructor
  PrintableInt(int value);
  // Converts the int into a string.
  std::string toString() const;
private:
  int m_value;
};
// PrintableInt.cpp
#include "stdafx.h"
#include "PrintableInt.h"
#include <sstream>

template<int T>
PrintableInt<T>::PrintableInt(int value)
{
  m_value = value;
}

template<int T>
std::string PrintableInt<T>::toString() const
{
  std::ostringstream builder;
  builder << m_value;
  return builder.str();
}

This adds the type parameter T to the class. Note that __declspec(dllimport) has been commented out to demonstrate the problem.

Note: The type parameter T serves no purpose in this implementation. It’s just there to demonstrate the problem.

Now, assume another project using the library project like this:

#include <iostream>
#include "PrintableInt.h"

int _tmain(int argc, _TCHAR* argv[])
{
  PrintableInt<6> test(5);
  std::cout << test.toString() << std::endl;
  return 0;
}

Without “dllimport” compiling this project will result in (rather cryptic) linker errors – namely “unresolved external symbol”. Uncommenting __declspec(dllimport) in PrintableInt.h again solves this problem.

Error window listing "unresolved external symbol" errors.

28 comments

  1. Hannu said: ∞

    This is one of the best Dll-tutorials I’ve ever seen. Thanks a lot!

  2. Yach said: ∞

    omg finally, i havent found one like this even on msdn

  3. Bandar said: ∞

    Wow Wow Wow. You’re awesome. I’ve been looking for these information for a while. You’re a lifesaver.

  4. Virat joshi said: ∞

    Sir I want code to access C# dll file in VC++
    Thank you Sir

  5. sahra said: ∞

    very good explained

  6. Fraz said: ∞

    Very well written … Thanks a lot

  7. Afreen said: ∞

    how to make an existing vc++ project as dll ..plz help

    • Sebastian Krysmanski (post author) replied: ∞

      In the project properties under “General” -> “Configuration Type” choose “Dynamic Library (.dll)”.

  8. Souleymen said: ∞

    thank you very much for all this shared knowledge !! this subject used to seem uncelar and difficult to follow in the past, you just changed that

  9. C++Noob said: ∞

    Thank you very much for this wonderful tutorial! It is one of the best I’ve ever seen.
    Just one question:
    If I do all your steps but can’t see the exported classes/functions in the object explorer (in VB.NET in my case), what did I do wrong?
    (I can make a reference to the created *.dll, but Intellisense doesn’t help if I try to type new code with classes/functions from this *.dll).

    • Sebastian Krysmanski (post author) replied: ∞

      I’m not a 100% certain but I think the object browser only shows .NET classes – not native C++ classes.

      You shouldn’t be able to use native C++ classes anyway. To workaround this, either use pure C functions and P/Invoke, or use C++/CLI.

  10. thanh son nguyen said: ∞

    Thank you very much. Your tutorial is helpful for me.

  11. Walter said: ∞

    Has it appeared to you that you cannot implement static libs into forms applications of VS C++ 2010…..smart guy!!!!!!!

    • Eric replied: ∞

      Yes you can – see my post of 25th January 2015 below.

  12. krishna said: ∞

    Hi , I have c++ dll which one having export class method. also some dependency on some other c++ class .i want to expose all this dll methos in my c# class ..please help me on it

    with sample codee

    Thanks.

  13. Eric said: ∞

    Hi, I am trying to follow your great guidance (thank you very much for this). But right at the beginning I get dozens of errors from the attempted compile from the assembyinfo.cpp which wants to use a whole lot of System namespaces which it can’t find. I am using VC++ 2010 express edition.

    Also, I would like to progress to making a dll with a function rather than a class – do you have specific guidance for this?

    many thanks in anticipation, Eric.

    • Eric replied: ∞

      OK, you have to create it as a Win32 project, not a class project and then stage 1 compiles OK.

      Sorry to have bothered you!

      But I’d still like your advice on the function rather than class bit if you can.

      Thank you.

    • Sebastian Krysmanski (post author) replied: ∞

      Just try using MYLIBRARY_EXPORT with a function rather than a class. You may also want to have a look at this MSDN article.

  14. Eric said: ∞

    Thank you very much for responding to my blog post. I tried your suggestion but I can’t get the code syntax right for a function that receives a string plus two integers and returns a string. I keep getting conflicts between the declaration in the header file and the function definition itself in the .cpp file. The ‘signature’ that I’m trying is std::string functionName(std::string, int, int). However, I have been able to build on your class example above and turned the class method into this ‘signature’ OK (many thanks again).
    Greetings to Stuttgart from South East Queensland, Australia:-)

    • Sebastian Krysmanski (post author) replied: ∞

      I guess, if you want to use C++ classes as parameters (std::string), then you have to get rid of the extern "C" part. Also make sure that the implementation of the function is actually in a .cpp file.

  15. Eric said: ∞

    Thank you again for getting back to me – I appreciate it very much. I will keep trying! I created a small native C++ program to utilise/call the class and its method and that works fine with the function ‘signature’ as per above, though there are some compiler warnings. But I have been totally unsuccessful in utilising the class and its method from a managed Visual C++ Windows form application. I have scoured the ‘net for guidance on invoking a native C/C++ DLL from a managed Windows form application but so far at least have not found an example that I can get to work.
    This whole process seems unnecessarily difficult!
    But again, many thanks for your replies.
    Totally unrelated, my Father was born in Stuttgart but he has been deceased for many years now.
    Best regards, Eric.

  16. Eric said: ∞

    Hi, I have made some progress, again thanks to your guidance above. After a LOT of fiddling and trial and error, have created both a function as a .dll and as a .lib and have been able to write small C++ console programs to use them

    Next I will try to use the .lib version in a managed Windows form application!

    Cheers.

  17. Eric said: ∞

    Hi, thanks to your guidance and some more trial and error I finally succeeded in creating a native C++ library that can be called from a managed Windows Form application.

    Your guidance has been most helpful!

    Cheers

  18. samsim said: ∞

    The program works perfectly. Thanks to the author for such a useful material, very useful to me. I will continue to visit your site.

  19. MATT said: ∞

    Good tutorial. Thanks.
    The title is called Creating a DLL project but then you say…”To make it a static library project, head to the project’s settings (available through the project’s context menu) and set Configuration Type to Static library (.lib)”.
    I don’t understand this part.. Can you explain please?

    • Sebastian Krysmanski (post author) replied: ∞

      You’re absolutely right. This is totally wrong. I can’t imagine why I wrote this part about the static library. Anyways, I’ve fixed it now.

  20. oddy said: ∞

    Thanks! Very nice.

  21. Alan said: ∞

    After days of attempts at getting a DLL written in C++ to work, this article fixed the problem. With just one simple addition that I SHOULD have seen before. Actually I did see it didn’t pay attention to it. Thanks for the most useful tutorial on the net…

Leave a Reply

Your email address will not be published. Required fields are marked *