Create a DLL in C and link it from a C++ project

10,299

Solution 1

You have several problems:

  1. The header file should mark the functions as exported when being compiled in the DLL but imported when being compiled by a library user.
  2. The header file should wrap the function declarations in an extern "C" block when being compiled as C++ to ensure that the names do not get mangled
  3. The DLL is not on your executable's library search path, so it can't be found at runtime.

To fix (1) and (2), rewrite your header like this:

#ifdef __cplusplus
extern "C" {
#endif

// Assume this symbol is only defined by your DLL project, so we can either
// export or import the symbols as appropriate
#if COMPILING_MY_TEST_DLL
#define TESTLIB_EXPORT __declspec(dllexport)
#else
#define TESTLIB_EXPORT __declspec(dllimport)
#endif

TESTLIB_EXPORT void hello();
// ... more function declarations, marked with TESTLIB_EXPORT

#ifdef __cplusplus
}
#endif

To fix (3), copy the DLL into the same folder as your executable file. The "executable directories" setting you're setting doesn't affect DLL searching -- see MSDN for a detailed description of how DLLs are searched for. The best solution for you is to copy your DLL into the directory where your executable file lives. You can either do this manually, or add a post-build step to your project that does this for you.

Solution 2

You should extern "C" the include:

extern "C" {
    #include <testlib.h>
}

Solution 3

It looks as if you need to make sure the compiler not mangle the symbol name in the cpp build. You should be able to add an extern "C" to the definition in testlib.h:

#ifdef __cplusplus
extern "C"
#endif
__declspec(dllexport) void hello();

Solution 4

Here's a method for your C header file that could be included by C++. Make sure to set TESTLIB_EXPORTS only in your DLL preprocessor settings. In projects that include this header to use the DLL, the header will declare the functions as imports instead of exports.

The __cplusplus guard will tell the compiler to import your functions using C name decoration instead of C++ name decoration.

#include <stdio.h>

#ifdef TESTLIB_EXPORTS
#define TESTLIB_API __declspec(dllexport)
#else
#define TESTLIB_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

TESTLIB_API void hello();
/* other prototypes here */

#ifdef __cplusplus
}
#endif
Share:
10,299
Manlio
Author by

Manlio

.

Updated on June 05, 2022

Comments

  • Manlio
    Manlio almost 2 years

    As per title, I'm trying to build a DLL using C and link it from a C++ project. I read and followed different tutorials on internet but everytime there is something missing and I don't understand what.

    Here's what I did, step by step:

    I created a new Win32 project, named testlib, then, from the wizard, I chose "DLL" and "Empty project".

    Added a header:

    //testlib.h
    
    #include <stdio.h>
    
    __declspec(dllexport) void hello();
    

    Added a source; since I want it to be a C source I read I should simplly rename the .cpp file in .c, so

    //testlib.c
    
    #include "testlib.h"
    
    void hello() {
        printf("DLL hello() called\n");
    }
    

    Build succeded.

    Now I would like to use my useful dll in another project.

    Then: new project (testlibUse). This time I selected "Empty project".
    No need to add an header, just created a cpp source

    //main.cpp
    #include <testlib.h>
    
    int main() {
        hello();
    }
    

    Then:

    • I added the path to the folder where is testlib.dll in Properties->VC++ directories->Executable directories

    • I added the path to the folder where is testlib.h in Properties->VC++ directories->Include directories

    • I added the path to testlib.lib (included extension) in Properties->Linker->Input->Additional dependencies

    I tried to build but I got a linker error:

    LINK : C:\path\testlibUse\Debug\testlibUse.exe not found or not built by the last incremental link; performing full link
    main.obj : error LNK2019: unresolved external symbol "void __cdecl hello(void)" (?hello@@YAXXZ) referenced in function _main
    C:\path\testlibUse\Debug\testlibUse.exe : fatal error LNK1120: 1 unresolved externals

    If I go back to testlib, rename back testlib.c in testlib.cpp and rebuild the dll, then I am able to build testlibUse but I get a "dll not found" error at runtime.

    I tried also to change the configurations of both projects in "Release" (changing the path where needed), but nothing changed.

    Sorry for the long post but I think it was necessary to write down exactly what I did.

    Any suggestions?

    Besides, are there any configuration parameters I need to change if I want to use my dll in a Qt project?

  • Manlio
    Manlio about 12 years
    Build successful but I get a "dll not found" error at runtime...Wasn't enough to add the path to the dll in Properties->VC++ directories->Executable directories?
  • Manlio
    Manlio about 12 years
    Build successful but I get a "dll not found" error at runtime...Wasn't enough to add the path to the dll in Properties->VC++ directories->Executable directories?
  • Mark Wilkins
    Mark Wilkins about 12 years
    @Saphrosit: No, to the best of my knowledge, that would not affect the running of the app. Read the description on that property page; it affects the finding of binaries while building the project. You need the DLL to be found (e.g., via PATH environment variable) at runtime.
  • Mohammed Noureldin
    Mohammed Noureldin about 5 years
    I would like to add a notice which deserves to be mentioned, that most C++ compilers automatically defines __cplusplus macro.
  • Adam Rosenfield
    Adam Rosenfield almost 5 years
    @MohammedNoureldin: All C++ compilers automatically define the __cplusplus macro when compiling C++ code. It's required by all C++ standards dating back to 1998.