[c++] Compile a DLL in C/C++, then call it from another program

I want to make a simple, simple DLL which exports one or two functions, then try to call it from another program... Everywhere I've looked so far, is for complicated matters, different ways of linking things together, weird problems that I haven't even begun to realize exist yet... I just want to get started, by doing something like so:

Make a DLL which exports some functions, like,

int add2(int num){
   return num + 2;
}

int mult(int num1, int num2){
   int product;
   product = num1 * num2;
   return product;
}

I'm compiling with MinGW, I'd like to do this in C, but if there's any real differences doing it in C++, I'd like to know those also. I want to know how to load that DLL into another C (and C++) program, and then call those functions from it. My goal here, after playing around with DLLs for a bit, is to make a VB front-end for C(++) code, by loading DLLs into visual basic (I have visual studio 6, I just want to make some forms and events for the objects on those forms, which call the DLL).

I need to know how to call gcc (/g++) to make it create a DLL, but also how to write (/generate) an exports file... and what I can/cannot do in a DLL (like, can I take arguments by pointer/reference from the VB front-end? Can the DLL call a theoretical function in the front-end? Or have a function take a "function pointer" (I don't even know if that's possible) from VB and call it?) I'm fairly certain I can't pass a variant to the DLL...but that's all I know really.

update again

Okay, I figured out how to compile it with gcc, to make the dll I ran

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a

and then I had another program load it and test the functions, and it worked great, thanks so much for the advice, but I tried loading it with VB6, like this

Public Declare Function add2 Lib "C:\c\dll\mydll.dll" (num As Integer) As Integer

then I just called add2(text1.text) from a form, but it gave me a runtime error:

"Can't find DLL entry point add2 in C:\c\dll\mydll.dll"

this is the code I compiled for the DLL:

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

EXPORT int __stdcall add2(int num){
  return num + 2;
}

EXPORT int __stdcall mul(int num1, int num2){
  return num1 * num2;
}

calling it from the C program like this worked, though:

#include<stdio.h>
#include<windows.h>

int main(){

  HANDLE ldll;
  int (*add2)(int);
  int (*mul)(int,int);

  ldll = LoadLibrary("mydll.dll");
  if(ldll>(void*)HINSTANCE_ERROR){
    add2 = GetProcAddress(ldll, "add2");
    mul = GetProcAddress(ldll, "mul");
    printf("add2(3): %d\nmul(4,5): %d", add2(3), mul(4,5));
  } else {
    printf("ERROR.");
  }

}

any ideas?

solved it

To solve the previous problem, I just had to compile it like so:

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias

and use this API call in VB6

Public Declare Function add2 Lib "C:\c\dll\mydll" _
    (ByVal num As Integer) As Integer

I learned not to forget to specify ByVal or ByRef explicitly--I was just getting back the address of the argument I passed, it looked like, -3048.

This question is related to c++ c dll gcc vb6

The answer is


Here is how you do it:

In .h

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

extern "C" // Only if you are using C++ rather than C
{    
  EXPORT int __stdcall add2(int num);
  EXPORT int __stdcall mult(int num1, int num2);
}

in .cpp

extern "C" // Only if you are using C++ rather than C
{    
EXPORT int __stdcall add2(int num)
{
  return num + 2;
}


EXPORT int __stdcall mult(int num1, int num2)
{
  int product;
  product = num1 * num2;
  return product;
}
}

The macro tells your module (i.e your .cpp files) that they are providing the dll stuff to the outside world. People who incude your .h file want to import the same functions, so they sell EXPORT as telling the linker to import. You need to add BUILD_DLL to the project compile options, and you might want to rename it to something obviously specific to your project (in case a dll uses your dll).

You might also need to create a .def file to rename the functions and de-obfuscate the names (C/C++ mangles those names). This blog entry might be an interesting launching off point about that.

Loading your own custom dlls is just like loading system dlls. Just ensure that the DLL is on your system path. C:\windows\ or the working dir of your application are an easy place to put your dll.


There is but one difference. You have to take care or name mangling win C++. But on windows you have to take care about 1) decrating the functions to be exported from the DLL 2) write a so called .def file which lists all the exported symbols.

In Windows while compiling a DLL have have to use

__declspec(dllexport)

but while using it you have to write __declspec(dllimport)

So the usual way of doing that is something like

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

The naming is a bit confusing, because it is often named EXPORT.. But that's what you'll find in most of the headers somwhere. So in your case you'd write (with the above #define)

int DLL_EXPORT add.... int DLL_EXPORT mult...

Remember that you have to add the Preprocessor directive BUILD_DLL during building the shared library.

Regards Friedrich


For VB6:

You need to declare your C functions as __stdcall, otherwise you get "invalid calling convention" type errors. About other your questions:

can I take arguments by pointer/reference from the VB front-end?

Yes, use ByRef/ByVal modifiers.

Can the DLL call a theoretical function in the front-end?

Yes, use AddressOf statement. You need to pass function pointer to dll before.

Or have a function take a "function pointer" (I don't even know if that's possible) from VB and call it?)

Yes, use AddressOf statement.

update (more questions appeared :)):

to load it into VB, do I just do the usual method (what I would do to load winsock.ocx or some other runtime, but find my DLL instead) or do I put an API call into a module?

You need to decaler API function in VB6 code, like next:

Private Declare Function SHGetSpecialFolderLocation Lib "shell32" _
   (ByVal hwndOwner As Long, _
    ByVal nFolder As Long, _
    ByRef pidl As Long) As Long

The thing to watch out for when writing C++ dlls is name mangling. If you want interoperability between C and C++, you'd be better off by exporting non-mangled C-style functions from within the dll.

You have two options to use a dll

  • Either use a lib file to link the symbols -- compile time dynamic linking
  • Use LoadLibrary() or some suitable function to load the library, retrieve a function pointer (GetProcAddress) and call it -- runtime dynamic linking

Exporting classes will not work if you follow the second method though.


Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to dll

The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing while starting Apache server on my computer PHP 7: Missing VCRUNTIME140.dll How to fix PHP Warning: PHP Startup: Unable to load dynamic library 'ext\\php_curl.dll'? WampServer: php-win.exe The program can't start because MSVCR110.dll is missing msvcr110.dll is missing from computer error while installing PHP installing JDK8 on Windows XP - advapi32.dll error The program can’t start because MSVCR71.dll is missing from your computer. Try reinstalling the program to fix this program ImportError: DLL load failed: %1 is not a valid Win32 application. But the DLL's are there Loading DLLs at runtime in C# Missing `server' JVM (Java\jre7\bin\server\jvm.dll.)

Examples related to gcc

Can't compile C program on a Mac after upgrade to Mojave Compiling an application for use in highly radioactive environments Make Error 127 when running trying to compile code How to Install gcc 5.3 with yum on CentOS 7.2? How does one set up the Visual Studio Code compiler/debugger to GCC? How do I set up CLion to compile and run? CMake error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found How to printf a 64-bit integer as hex? Differences between arm64 and aarch64 Fatal error: iostream: No such file or directory in compiling C program using GCC

Examples related to vb6

Add newline to VBA or Visual Basic 6 Visual Studio 6 Windows Common Controls 6.0 (sp6) Windows 7, 64 bit ReDim Preserve to a Multi-Dimensional Array in Visual Basic 6 Object Library Not Registered When Adding Windows Common Controls 6.0 VB6 IDE cannot load MSCOMCTL.OCX after update KB 2687323 VBA Convert String to Date Installation of VB6 on Windows 7 / 8 / 10 Escape double quote in VB string How do I resolve "Run-time error '429': ActiveX component can't create object"? What is the difference between dim and set in vba