2
votes

So I am trying to export into a dll a class that uses a class from another dll. An example will explain the situation better.

//aclass.h
class  __declspec(dllexport) aclass{
    public:
        void amethod();
};

_

//aclass.cpp
#include "aclass.h"

void aclass::amethod(){
    std::cout<<"a method"<<std::endl;
}

So without including anything external this compiles (aclass.dll) and runs from other projects, ex.

#include <aclass.h>

void main(){
    aclass a;
    a.amethod();

    _getch();
}

The problem arises when I include an external header (that comes with a dll and a lib file, the paths of which are passed to the compiler). As soon as I include the external header:

//aclass.h
#include <externalapi.h>
class  __declspec(dllexport) aclass{
    public
    void amethod();
};

without even calling any class of function from the externalapi, when try to compile I get:

Error 1 error LNK2001: unresolved external symbol __imp__Math_e C:\...\aclass.obj  aclass
Error 1 error LNK2001: unresolved external symbol __imp__Math_pi C:\...\aclass.obj aclass
Error 1 error LNK2001: unresolved external symbol __imp__Math_zero C:\...\aclass.obj aclass
....etc

Originally (without the __declspec(dllexport) directive) I would access these by something like:

Math::pi;
Math::e;
etc.

as they are static constants of the externalapi. From what I understand on how the whole thing with dll exporting works, this is what is called name mangling(?). So two questions:

  1. What should I change in the syntax so that the function names of the external library are "loaded" with their original c++ names? This has to be somehow possible. Up until now I was developing my code, as a stand-alone application, meaning that I was not using the __declspec(dllexport) keywords, I was including the same header file, using the exact same dll and lib file and everything was compiling and running smoothly. Obviously, the code above is a oversimplification of my actual code to point out the problem.
  2. In most of the "export to dll" how-to I have found around, people use __declspec(dllexport) and __declspec(dllimport). I understand __declspec(dllexport) more or less tells the compiler to export the part of code to dll, and this makes sense. What exactly is the meaning of __declspec(dllimport). For instance why is this first piece of code, I wrote at the beginning, compiling and usable as a dll without the need of __declspec(dllimport)?

Thanks for your time!

2

2 Answers

2
votes

__declspec(dllimport) tells the compiler that the function will be imported from a DLL using an import LIB, rather than found in a different OBJ file or a static LIB.

BTW: it sounds like you may not want DLLs at all. DLLs are specifically for swapping out the library after compilation without having to recompile the application, or for sharing large amounts of object code between applications. If all you want is to reuse a set of code between different projects without having to compile it for each one, static libraries are sufficient, and easier to reason about.

1
votes

It's usually best to have a conditional macro that imports or exports depending

#ifdef MODULE1
#define MODULE1_DECL __declspec(dllexport)
#else
#define MODULE1_DECL __declspec(dllimport)
#endif

This way you export functions etc that you want to export, and import what you want to use. For example see this SO post
You #define MODULE1 (maybe as a setting) in your project that will export definitions, and use the MODULE1_DECL define rather than explicitly putting either __declspec(dllimport) or __declspec(dllexport) in your code. Read the manual for further details.
Name mangling just happens in C++: it indicates namespaces, and the parameters a function overload etc. takes for disambiguation.