Visual C++: Exporting functions from a DLL using “__declspec(dllexport)” keyword.

DLL – Dynamic Link Libraries are the shared libraries those can be used by multiple applications, at a time.

In this article I am going to explain the steps to export functions from a DLL. So the exported functions can be called from other programs.

What functions to export from the DLL? That thing you need to decide based on your requirements.

Once the exported functions are identified, you can export from a DLL in two ways. One is by using “.def” file and another one is using the keyword “__declspec(dllexport)”. You can use either one to export the functions from a DLL. In this article I am using “__declspec(dllexport)” keyword to export the functions.

Lets create a simple DLL to export a function ‘SayHello’.

Step 1. We will add a simple function ‘SayHello’ into the DLL code. This function will just print “Hello, World!” on the console window. Remember that we are going to export this function from the DLL; hence we need to add “__declspec(dllexport)” keyword before the function signature. The code looks like below:

//sample.cpp
#include <stdio.h>

__declspec(dllexport) void SayHello()
{
	printf("Hello, World!\n");
}

Step 2. Now we need to compile this “sample.cpp” file. We are going to generate a DLL file; hence main() function is not required to add within the file “sample.cpp”. To compile the file, use the below command at the command prompt:

cl sample.cpp /LD /EHsc

Above command compiles “sample.cpp” code and generates the following files:

sample.dll
sample.exp
sample.lib
sample.obj

Step 3. Our DLL is ready. It exports “SayHello” function. We need to write a test application to call “SayHello” function. Lets write a test application; it is so simple. The code looks like below:

//TestApp.cpp
extern void SayHello();

void main()
{
   SayHello();
}

Observe that from above code, we have added “extern” keyword in front of the “SayHello” function. It tells to the compiler, that the function is defined in other module. If we omit this line, when we compile the file, compiler will throw below error:

TestApp.cpp(5) : error C3861: ‘SayHello’: identifier not found

Step 4. Our test application is ready; we need to compile it, to generate an EXE file (executable file). But we have to be careful while compiling test application; we need to link “sample.lib” file when we generate EXE file. Because our function definition exists in inside “sample.dll” file; so we need to link the DLL file. If we don’t link “sample.lib”, compiler will throw the error “error C3861” which was mentioned in the above step.

So the command will looks like below:

cl TestApp.cpp /EHsc /link sample.lib

This command will generate “TestApp.exe” file and when we ran it, it will display “Hello, World!” message on the screen.

It is confirmed that our DLL is working fine with the test application written in “C++”.

Can we use our DLL in Visual Basic projects? Lets check this also.

Step 1. Create a Visual Basic “Console Application” project using Visual Studio 2012.

Step 2. In order to use a function from a DLL, first we need to declare a function based on the DLL. So we need to add below declare statement in the Visual Basic code.

Declare Sub SayHello Lib "sample.dll" Alias "?SayHello@@YAXXZ" ()

We need to specify the path to “sample.dll” file, if the DLL is not copied into the Visual Basic Project’s “bin/Debug” or “bin/Release” folder (Depending on your project’s configuration). Otherwise, Visual Basic will throw the below exception:

Unhandled Exception: System.DllNotFoundException: Unable to load DLL ‘sample.dll
‘: The specified module could not be found. (Exception from HRESULT: 0x8007007E)

at TestVBApp.Module1.SayHello()
at TestVBApp.Module1.Main() in C:\visual studio 2012

Step 3. Once the function is declared, we need to call the function. Whole code looks like below:

Module Module1
    Declare Sub SayHello Lib "sample.dll" Alias "?SayHello@@YAXXZ" ()

    Sub Main()
        Call SayHello()
    End Sub

End Module

Step 4. Run the program and you will see “Hello, World!” message will be displayed on the console window.

Our DLL is working fine even with Visual Basic project.

But there is a problem here. Whenever we re-compile our DLL code with latest version of the compiler; there are chances to change the exported function names. Correct; what you read is correct. We have declared our function as “SayHello”, but when we compile our DLL code, “C++” compiler will decorate the function names and export the decorated function names instead of actual names. This is the “C++” style of generating function names. We can’t directly call the function “SayHello” from other languages like “C” or “Visual Basic”. Because there will be no “SayHello” function in the code generated by the “C++” compiler; it generates the code with decorated name “?SayHello@@YAXXZ”. Hence in the above Visual Basic code we have used “Alias” section in “Declare” statement to mention decorated name of the function. Finally it worked and displayed “Hello, World!” on the screen.

But we need to change the alias name in our Visual Basic project and re-build the project, whenever the decorated name of the DLL function changed. This is a bit painful job.

Can’t we avoid this problem? Yes. We can. The solution is, instruct “C++” compiler to not to generate decorated names. So the “C++” compiler will generate the DLL with actual function names and these can be accessible from “C” or “Visual Basic” project.

We can achieve this simply by adding extern “C” keyword before the exported function in our DLL code “sample.cpp”. After adding this, the function declaration looks like below:

extern "C" __declspec(dllexport) void SayHello()

Re-compile the code to generate the DLL.

If we run our test application “TestApp.exe”, it will through the error:

The procedure entry point ?SayHello@@YAXXZ could not be located in the dynamic link library sample.dll.

That signals, to re-compile our test application “TestApp.cpp” also. Before re-compiling our test application we should add extern “C” keyword before the function declaration “SayHello”.

extern "C" void SayHello();

Otherwise, “C++” compiler will throw the below exception:

TestApp.obj : error LNK2019: unresolved external symbol “void __cdecl SayHello(void)” (?SayHello@@YAXXZ) referenced in function _main
TestApp.exe : fatal error LNK1120: 1 unresolved externals

After these changes, our test application “TestApp.exe” will work as we expected.

What about our Visual Basic test application? We need to change our Visual Basic application’ code also. Just remove the “Alias” section from the declaration statement and re-build the project.

Declare Sub SayHello Lib "sample.dll" ()

Once we run the Visual Basic application, it will display “Hello, World!” message on the screen.

We are successfully created a DLL and tested in “C++” and “Visual Basic” applications.

As I discussed earlier, we can export the functions from DLLs using “.DEF” files also. Lets discuss about this in our next article.

**

1 comment for “Visual C++: Exporting functions from a DLL using “__declspec(dllexport)” keyword.

Leave a Reply