Error: function definition is marked dllimport

Learn error: function definition is marked dllimport with practical examples, diagrams, and best practices. Covers c++, qt, dllimport development techniques with visual explanations.

Resolving 'function definition is marked dllimport' in C++ and Qt

Hero image for Error: function definition is marked dllimport

Understand and fix the common C++ compilation error 'function definition is marked dllimport' when working with DLLs, especially in Qt projects.

The error message "function definition is marked dllimport" is a common pitfall for C++ developers working with Dynamic Link Libraries (DLLs), particularly in cross-platform frameworks like Qt. This error typically arises when the compiler encounters a function definition that has been incorrectly marked for import, rather than export, from a DLL. This article will demystify the __declspec(dllimport) and __declspec(dllexport) keywords, explain why this error occurs, and provide practical solutions to resolve it in your C++ and Qt projects.

Understanding dllimport and dllexport

In Windows programming, __declspec(dllimport) and __declspec(dllexport) are Microsoft-specific extensions used to declare functions, variables, or classes as being imported from or exported to a DLL. These keywords are crucial for the linker to correctly resolve symbols when building executables or other DLLs that depend on your library.

  • __declspec(dllexport): This keyword is used when defining a function or class within the DLL project itself. It tells the compiler to place the function's name in the DLL's export table, making it available for other modules to link against.
  • __declspec(dllimport): This keyword is used when declaring a function or class in a header file that will be included by a client application (or another DLL) that uses your DLL. It tells the compiler that the definition for this symbol will be found in an external DLL, allowing it to generate more efficient code by avoiding an extra level of indirection.
flowchart TD
    subgraph DLL Project
        A[Source Code (.cpp)] --> B{__declspec(dllexport)}
        B --> C[DLL Export Table]
    end

    subgraph Client Project
        D[Header File (.h)] --> E{__declspec(dllimport)}
        E --> F[Client Executable/DLL]
    end

    C --"Provides Symbols"--> F

Flow of dllexport and dllimport in DLL creation and usage

The Root Cause of the Error

The error "function definition is marked dllimport" occurs when you attempt to define a function (i.e., provide its implementation) while it is simultaneously marked with __declspec(dllimport). The compiler expects dllimport declarations to refer to symbols whose definitions reside outside the current compilation unit, typically in a separate DLL. When it finds a definition for an dllimport-marked symbol, it flags this as an error because it's a logical contradiction: you're telling the compiler to import something that you're also defining locally.

This usually happens due to incorrect preprocessor macro usage, where the same header file is used for both building the DLL itself and for consuming the DLL, but the macros controlling dllexport vs. dllimport are not set up correctly for the current build context.

Common Solutions and Best Practices

The standard approach to manage dllexport and dllimport is to use preprocessor macros. This allows the same header file to serve both the DLL's internal compilation and external client usage without modification.

Here's a typical pattern:

  1. Define a macro (e.g., MYLIB_EXPORT) that expands to __declspec(dllexport) when building the DLL and __declspec(dllimport) when consuming it.
  2. Use a project-specific define (e.g., MYLIB_EXPORTS) that is only defined when compiling the DLL project.
  3. Apply the macro to all classes, functions, and variables that you intend to export from your DLL.
#ifndef MYLIB_GLOBAL_H
#define MYLIB_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(MYLIB_EXPORTS)
#  define MYLIB_EXPORT Q_DECL_EXPORT
#else
#  define MYLIB_EXPORT Q_DECL_IMPORT
#endif

#endif // MYLIB_GLOBAL_H

Example of a global header for DLL export/import management (e.g., mylib_global.h)

In Qt projects, Q_DECL_EXPORT and Q_DECL_IMPORT are convenient macros provided by Qt that abstract away the platform-specific __declspec keywords (and handle GCC's __attribute__((visibility("default"))) for Linux/macOS). This makes your code more portable.

Then, in your class or function declarations:

// mylib.h
#include "mylib_global.h"

class MYLIB_EXPORT MyClass {
public:
    MyClass();
    void doSomething();
};

MYLIB_EXPORT void myFunction();

Applying the MYLIB_EXPORT macro to a class and a function

graph TD
    A[Start Build Process]
    A --> B{Is current project building the DLL?}
    B -- Yes --> C[Define MYLIB_EXPORTS]
    B -- No --> D[Do NOT define MYLIB_EXPORTS]
    C --> E[Compile DLL Source Files]
    D --> F[Compile Client Source Files]
    E --> G[DLL Output (.dll, .lib)]
    F --> H[Client Executable/DLL]
    G -- Link against --> H

Decision flow for defining MYLIB_EXPORTS during compilation

1. Step 1: Create a Global Export Header

Create a header file (e.g., yourlib_global.h) that defines your export macro using Q_DECL_EXPORT and Q_DECL_IMPORT based on a preprocessor symbol (e.g., YOURLIB_EXPORTS).

2. Step 2: Apply the Macro to Your DLL's Public API

Prefix all classes, functions, and global variables that you want to expose from your DLL with the newly defined export macro in their declarations within your DLL's public header files.

3. Step 3: Configure Project Settings

In your DLL project's build settings (e.g., .pro file in Qt Creator, or Visual Studio project properties), add YOURLIB_EXPORTS to the preprocessor definitions. Ensure this define is not present in any client projects that consume the DLL.

4. Step 4: Rebuild Your Projects

Clean and rebuild both your DLL project and any client projects that use it. This ensures all files are compiled with the correct dllimport/dllexport settings.