Reasoning behind dllexport/dllimport? - c++

I'm just a beginner in c++ and to me this seems like unnecessary code bloat. I understand that dllimport/export are used for sharing dll functionality, but what's wrong with just using public/private accessors?
If i am making a large dll library it seems that I have to go through every single function/class and make sure I export it. With managed dll (like from c#) I don't need to do anything. Import it into my project, and as long as the function is public it's accessible!

Because when you're creating a larger dll (or shared library) you may want to compose it of several object files, but don't want to expose all the public (to the linker) symbols in each object file. That is there are occations when a symbol is public in one of the object file for the only purpose to make it available to another object file in the same library.
Note that public and private accessors are not quite the same as private symbols in an object file. While private symbol in an object (fx created with global static qualifier) file means that the symbol is not visible at all outside the object file, while private accessors just mean that the symbol can't be accessed from outside the class (it still can make it into the object file as public since it could be accessed from the same class within another translation unit).
If you want to export all public symbols in the object files there may be a mechanism to do that without having to resort to explicitely mark each symbol as dllexport - you have to check the documentation, apparently there's a way in microsoft for that.
And for the story about dllimport you can read it here: Why/when is __declspec( dllimport ) not needed?

The idea is that your module can have some functionality that only it needs to run which exposing would be pointless. For example, if you have a Timer class you are exporting, and it depends on some global function you wrote to get the current time, you don't need to export said function, since users of your library don't depend on it directly.
Sorry about the bad example.. Also, you don't need to export your classes, use interfaces and factory functions.
//IBob.h
#define DLLAPI __cdecl
class IBob
{
public:
void DoSomething( ) = 0;
};
__declspec(/*export / import*/) IBob* DLLAPI BobFactory( );
//----------------------------------
//Bob.h
#include "IBob.h"
class Bob : public IBob
{
public:
void DoSomething( ) override
{
//implementation...
}
private:
int var;
int var2;
};
__declspec(dllexport) IBob* DLLAPI BobFactory( )
{
return new Bob( );
}

As said this is nothing to do with C++ and is just the way DLLs work in every language (.NET managed DLLs are different). When the OS loads a program with DLLs it must fix up all references in the EXE to functions exported from the DLL, so the less of them you use the faster the program loads. Probably in this day and age it makes little difference, but this goes back to the early versions of Windows.
BTW you can __declspec(dllexport) a whole class, which is the slightly lazy way of doing it.

Related

Pass pointer to object to dll

I'm writing this Editor.exe program that loads a game.dll, gets the address of a function inside the dll, and pass a pointer to a Core object.
gameInitFuncPtr init =
(gameInitFuncPtr) GetProcAddress(LoadLibraryA("game.dll"),"gameInit");
init(&core); // core is already instanced somewhere, maybe on the stack
The game.dll includes the core.h where the Core class is defined.
The Core class is implemented and compiled into Editor.exe.
On the dll side, calling functions from the passed object pointer, results in an Unresolved external symbol
An example of a call the game.dll would do with the given object pointer would be:
void gameInit(ldk::Core* core)
{
_core->renderer.drawText("initializing...");
}
How can I compile the dll so that it does not try to find, for example, the drawText() implementation within the dll module ?
1 - Please, note that this is NOT a question about how to declare pointers to member functions.
2 - I know it could easily be fixed if i passed a struct with only pointer to the methods, but I'm really curious about this.
3 - I'm using Microsoft's cl compiler 18.00, the one that ships with Visual studio 2013
It is not clear where you initiallize _core. At first glance gameInit should do it.
Declare interface class Core, i.e. it should be abstract. Implement it in a successor class for example CoreImpl in exe. This will fix Unresolved external symbols.
Looks like I was overthinking it.
Wen compiling the editor.exe the Core sould be declared just link any class.
struct Core
{
struct Renderer
{
void drawText(const char* text);
}
...
}
But, since the editor and the game.dll share the same Core.h, I used a macro to modify the declaration of Core.h member functions to be pure virtual, for example:
struct Core
{
struct Renderer
{
virtual void drawText(const char* text) = 0;
}
...
}
So the Unresolved external symbol linking error is gone
BUT: I does not work as expected in RUNTIME! :(
I had a similar problem as you with almost the same setting - Game as dll and Engine as exe. Here are some notes on how to tackle this problem.
Call only virtual methods. As you pointed out, if the method you call is not declared virtual, the linker tries to find an implementation for it and fails (if it's not in the header - a thing we try to avoid). The method does not need to be abstract, virtual is enough. Also, note that in your struct Renderer you can have methods that are not virtual, as long as you don't call them from the dll (if you do, the linker complains). It is probably not advisable to have such an interface, it would be much better to have some sort of API class which has only virtual public methods so users of this class cannot make a mistake.
All classes used from the dll need to be shared or header only. What I mean by this is, that as far as I know, there is no magic way, to have classes declared in header, implemented in cpp which is compiled to the exe and then use these classes from the dll. E.g., if you have a custom string class, it needs to be in a shared library. If it's just in the exe you will not be able to instantiate it in the dll (return it from functions etc.). A solution to this is to use header-only classes. E.g., your string may be implemented in a header in the Editor project and this header may be included by your Game project. This way you essentially compile the same code to both exe and dll.
To see a small working example see my repository with VS 2017 solution which demonstrates this exact problem and nothing else. repo link.
Much larger working example of this problem can be seen in idTech4 engine - DOOM 3 version here. It also uses a game as a dll and an engine as an exe. And also needs to exchange pointers to the engine's systems which are used from the game. The project is big, but if you take a look at project Game-d3xp class Game.h all the way down, they have the game's API with a single function GetGameAPI_t which expects to get gameImport_t struct with pointers to engine systems and returns gameExport_t with game informations. The loading then happens in the Common.cpp
As you can see they use shared library idLib in the respective project for things such as idString. All engine classes used from the dll are usually very small and implemented in headers only (they are mostly structs).
Note that id themselves are moving away from this architecture and even their latest version of DOOM 3 - DOOM 3 BFG edition compiles to a single exe and the modules are static libraries instead of dlls.

How do I set up a multi-project solution in C++?

I'm new to C++ and I'm having a hard time getting my dll references to work. I've been trying to get it to work for a couple of days, but the few explainations I've found often refer to doing x or y, but don't tell me how to do x or y. Since I'm not a C++ veteran, I need someone to walk me through it. What I want to do is the following:
MySolution
MyExe (Win32 .exe)
Main.h
Main.cpp
(constructs ImplementationB calls the methods as defined by InterfaceA, then deletes the instances)
(calls/fills HelperC.Foobar)
MyInterfaces (dll)
InterfaceA.h
~InterfaceA();
virtual void DoSomething();
MyUtils (dll)
HelperC.h
static float Foobar;
HelperD.cpp
float HelperC::Foobar = 1.0f;
MyImplementations (dll)
ImplementationB : InterfaceA
(uses the value from HelperC.Foobar)
The MyExe and MyImplementations projects contain most of the executing code. But, I need an interface, so I need an interface project (MyInterfaces). I need some helper classes that need to be accessible from both MyExe and MyImplementations, hence MyUtils. I would like this helper class to be statically available, though it is not mandatory.
I had a compiling version before I started adding MyUtils with the HelperC class. I had to mark the interface destructor with __declspec(dllexport), along with the DoSomething method. I also had to mark the constructor of ImplementationB in order to instantiate it from MyExe, which makes sense. However, when I tried to mark the entire class (both the implementation and the interface) with __declspec(dllexport), the example wouldn't compile (which does not make sense).
From what I've read, having static fields in a dll and using them from external code doesn't really work all too well. So, as an alternative, I made Foobar non-static and passed a HelperC instance to the method as described by InterfaceA. Since I had already gotten simple classes to work, I figured that should work as well. However, now the compiler is throwing errors on the constructor of ImplementationB (LNK2019).
In short: I'm getting link errors all over the place in sections that have nothing to do with my changes, and there's little documentation describing the specific steps I need to perform in order to get a simple dll reference to work.
Can someone point out what I need to add and where I need to add it in order to make it compile? Also, some do's and don't's about C++ dll references would help a lot (e.g. don't use statics across projects).
After much digging, I found out that the culprit was a magical project setting. It is called Ignore Import Library and is located at Project Properties->Linker->General, and is set to Yes by default, while it should be set to No in most cases. The setting tells the executable project to use the dll's lib file during compilation. This still sounds strange to me (sounds like duplicate build output), but as far as I understand it, the lib file describes how to link to the dll. If your dll produces a lib during build, you probably want to set the setting to No.
I also learned that to be able to use the HelperC class as a statically accessible helper, I needed to use dllimport in combination with the macro trick, as described by #drescherjm. The dllimport declaration is only ever needed to be able to use data members across libraries (static class fields or globally defined variables). It may be applied to functions as well, though it is not required, in which case it provides a slight performance boost during library linking.
For completeness, my project structure after getting it to work:
MySolution
MyExe (Win32 .exe, Debugger Type=Mixed)
Main.h
Main.cpp
(constructs ImplementationB calls the methods as defined by InterfaceA, then deletes the instances)
(calls/fills HelperC::Foobar)
MyInterfaces (dll, Ignore Import Library=Yes, because there is no .lib after building)
InterfaceA.h
class __declspec(dllexport) InterfaceA
~InterfaceA() {};
virtual void DoSomething() = 0;
MyUtils (dll, Ignore Import Library=No)
HelperC.h
class __declspec(dllimport/dllexport) HelperC // (see macro trick)
static float Foobar;
HelperD.cpp
float HelperC::Foobar = 1.0f;
MyImplementations (dll, Ignore Import Library=No)
ImplementationB.h
class __declspec(dllexport) ImplementationB : public InterfaceA
ImplementationB();
~ImplementationB();
void DoSomething();
ImplementationB.cpp
ImplementationB::ImplementationB() {};
ImplementationB::~ImplementationB() {};
ImplementationB::DoSomething() { /* Omitted */ };
(uses HelperC::Foobar in implementation)
On a side note: if you added a default C++ class library project in Visual Studio, you may need to flip the Project Properties->Debugging->Debugger Type setting to Mixed before you will be able to set/use breakpoints in the dll code. See this.
I hope this helps others who are wrestling with dll's in C++ (and Visual Studio).

Wrapping different C API implementations in C++

assume we were using gcc/g++ and a C API specified by a random committee. This specification defines the function
void foo(void);
Now, there are several implementations according to this specification. Let's pick two as a sample and call them nfoo and xfoo (provided by libnfoo and libxfoo as static and dynamic libraries respectively).
Now, we want to create a C++ framework for the foo-API. Thus, we specify an abstract class
class Foo
{
public:
virtual void foo(void) = 0;
};
and corresponding implementations
#include <nfoo.h>
#include "Foo.h"
class NFoo : public Foo
{
public:
virtual void foo(void)
{
::foo(); // calling foo from the nfoo C-API
}
};
as well as
#include <xfoo.h>
#include "Foo.h"
class XFoo : public Foo
{
public:
virtual void foo(void)
{
::foo(); // calling foo from the xfoo C-API
}
};
Now, we are facing a problem: How do we create (i.e. link) everything into one library?
I see that there will be a symbol clash with the foo function symbols of the C API implementations.
I already tried to split the C++ wrapper implementations into separate static libraries, but then I realized (again) that static libraries is just a collection of unlinked object files. So this will not work at all, unless there is a way to fully link the C libraries into the wrapper and remove/hide their symbols.
Suggestions are highly appreciated.
Update: Optimal solutions should support both implementations at the same time.
Note: The code is not meant to be functional. Perceive it as pseudo code.
Could you use dlopen/dlsym at runtime to resolve your foo call.
something like example code from link ( may not compile):
void *handle,*handle2;
void (*fnfoo)() = null;
void (*fxfoo)() = null;
/* open the needed object */
handle = dlopen("/usr/home/me/libnfoo.so", RTLD_LOCAL | RTLD_LAZY);
handle2 = dlopen("/usr/home/me/libxfoo.so", RTLD_LOCAL | RTLD_LAZY);
fnfoo = dlsym(handle, "foo");
fxfoo = dlsym(handle, "foo");
/* invoke function */
(*fnfoo)();
(*fxfoo)();
// don't forget dlclose()'s
otherwise, the symbols in the libraries would need to be modified.
this is not portable to windows.
First thing's first, if you are going to be wrapping up a C API in C++ code, you should hide that dependency behind a compilation firewall. This is to (1) avoid polluting the global namespace with the names from the C API, and (2) freeing the user-code from the dependency to the third-party headers. In this example, a rather trivial modification can be done to isolate the dependency to the C APIs. You should do this:
// In NFoo.h:
#include "Foo.h"
class NFoo : public Foo
{
public:
virtual void foo(void);
};
// In NFoo.cpp:
#include "NFoo.h"
#include <nfoo.h>
void NFoo::foo(void) {
::foo(); // calling foo from the nfoo C-API
}
The point of the above is that the C API header, <nfoo.h>, is only included in the cpp file, not in the header file. This means that user-code will not need to provide the C API headers in order to compile code that uses your library, nor will the global namespace names from the C API risk clashing with anything else being compiled. Also, if your C API (or any other external dependency for that matter) requires creating a number of things (e.g., handles, objects, etc.) when using the API, then you can also wrap them in a PImpl (pointer to a forward-declared implementation class that is only declared-defined in the cpp file) to achieve the same isolation of the external dependency (i.e., a "compilation firewall").
Now, that the basic stuff is out of the way, we can move to the issue at hand: simultaneously linking to two C APIs with name-clashing symbols. This is a problem and there is no easy way out. The compilation firewall technique above is really about isolating and minimizing dependencies during compilation, and by that, you could easily compile code that depends on two APIs with conflicting names (which isn't true in your version), however, you will still be hit hard with ODR (One Definition Rule) errors when reaching the linking phase.
This thread has a few useful tricks to resolving C API name conflicts. In summary, you have the following choices:
If you have access to static libraries (or object files) for at least one of the two C APIs, then you can use a utility like objcopy (in Unix/Linux) to add a prefix to all the symbols in that static library (object files), e.g., with the command objcopy --prefix-symbols=libn_ libn.o to prefix all the symbols in libn.o with libn_. Of course, this implies that you will need to add the same prefix to the declarations in the API's header file(s) (or make a reduced version with only what you need), but this is not a problem from a maintenance perspective as long as you have a proper compilation firewall in place for that external dependency.
If you don't have access to static libraries (or object files) or don't want to do this above (somewhat troublesome) approach, you will have to go with a dynamic library. However, this isn't as trivial as it sounds (and I'm not even gonna go into the topic of DLL Hell). You must use dynamic loading of the dynamic link library (or shared-object file), as opposed to the more usual static loading. That is, you must use the LoadLibrary / GetProcAddress / FreeLibrary (for Windows) and the dlopen / dlsym / dlclose (all Unix-like OSes). This means that you have to individually load and set the function-pointer address for each function that you wish to use. Again, if the dependencies are properly isolated in the code, this is going to be just a matter of writing all this repetitive code, but not much danger involved here.
If your uses of the C APIs is much simpler than the C APIs themselves (i.e., you use only a few functions out of hundreds of functions), it might be a lot easier for you to create two dynamic libraries, one for each C API, that exports only the limited subset of functions, giving them unique names, that wrap calls to the C API. Then, you main application or library can be link to those two dynamic libraries directly (statically loaded). Of course, if you need to do that for all the functions in that C API, then there is no point in going through all this trouble.
So, you can choose what seems more reasonable or feasible for you, there is no doubt that it will require quite a bit a manual work to fix this up.
if you only want to access one library implementation at a time, a natural way to go about it is as a dynamic library
in Windows that also works for accessing two or more library implementations at a time, because Windows dynamic libraries provide total encapsulation of whatever's inside
IIUC ifdef is what you need
put #define _NFOO
in the nfoo lib and #define XFOO in xfoo lib.
Also remember if nfoo lib and xfoo lib both have a function called Foo then there will be error during compilation. To avoid this GCC/G++ uses function overloading through name mangling.
you can then check if xfoo is linked using ifdefs
#ifdef XFOO
//call xfoo's foo()
#endif
A linker cannot distinguish between two different definitions of the same symbol name, so if you're trying to use two functions with the same name you'll have to separate them somehow.
The way to separate them is to put them in dynamic libraries. You can choose which things to export from a dynamic library, so you can export the wrappers while leaving the underlying API functions hidden. You can also load the dynamic library at runtime and bind to symbols one at a time, so even if the same name is define in more than one they won't interfere with each other.

How can design a config utility to work both statically and dynamically linked?

I feel this issue may have a simple solution that's just not obvious to me - I have a config class that is used to store various configuration options loaded from an ini file, among other places. In my application, I have a library and client, and 2 configurations - build the library as a DLL and have the client link dynamically, or build them both together as a single binary. So how can I have/use my config object in both the library and client? If I include the config class definition in both, I assume it will give me link errors due to redefinitions.
If I include the config class definition in both, I assume it will give me link errors due to redefinitions.
No, it won't. Windows DLLs do not respect the one definition rule. Basically, in Windows, ODR stops at the module boundary, i.e., ODR is respected within an executable and within a DLL, but not across them. Whether that's a good thing or not is not relevant, that's just how it is. So, you can include the definition of your config class in both the DLL and the executable. However, there will be two separate instances of the singleton (as I assume it is a singleton class, as config classes usually are), one in each module. In that sense, it won't be a true singleton, at least, not across the modules.
If you want a true singleton across the modules, you'll have to do a bit more work. You have two choices: master-slave or merging (or a "daisy chain").
The first option is to designate one module (e.g., the executable) as the module that instantiates (and keeps) the singleton object, and then you pass a pointer to that instance to all the "slave" modules which can then use it via a common interface (so both modules have the same declaration for the config class, but only one module creates it and passes it to the others). It would look something like this:
In the header file "config_class.h":
class ConfigClass {
// a bunch of declarations...
public:
static ConfigClass& getInstance(); // the access-point for the singleton.
};
#ifdef MY_LIB_NOW_BUILDING_MASTER
extern "C" __declspec(dllimport) void setConfigClassInstance(ConfigClass* pobj);
#else
extern "C" __declspec(dllexport) void setConfigClassInstance(ConfigClass* pobj);
#endif
In the cpp file "config_class.cpp":
#include "config_class.h"
// a bunch of definitions for the config_class member functions.
#ifdef MY_LIB_NOW_BUILDING_MASTER
ConfigClass& ConfigClass::getInstance() {
static ConfigClass instance( /* */ );
return instance;
};
#else
static ConfigClass* masterInstance;
void setConfigClassInstance(ConfigClass* pobj) {
masterInstance = pobj;
};
ConfigClass& ConfigClass::getInstance() {
return *masterInstance;
};
#endif
where, in the above example, you would call setConfigClassInstance from the master module (most likely the main executable) to set the config object for the DLLs, but make sure the DLLs don't require the config class during their static initialization (loading).
The second option is to either merge or daisy-chain your singletons. In this case, each module creates its own singleton instance, but then, using a similar scheme as above, they pass pointers to each other's instances, allowing them to be either merged into one instance (cross-linked), or you chain them together (e.g., like a circular linked-list or ring-list) and you dispatch the calls to the appropriate instance.
I think that for your application, the first option is probably the easiest.
N.B.: In non-Windows environments, the situation is entirely different, and none of the above applies.

In C++, how to use a singleton from a separate source file?

I'm trying to compile some other people's wrapper program on a large system, in which it's using a global object from another file, the definition of the class is like:
class __declspec(dllexport) A
{
...
static A * instance;
}
And in my separate source file (which I want to build to a .exe), I included the header file A.h, and declare at the beginning like this
A * A::instance;
to access the data in A.
The problem is, this piece of code can be built successfully on Linux, now when I try to build it in windows NT, it will have issues.
If I leave it like this, the compiler will complain with a C2491 error, definition of dllimport function not allowed.
If I remove this line of A declaration, I'll get a lot of error LNK2001: unresolved external symbol.
Not quite sure what is the problem here, I did some research online, but couldn't find a good answer, I myself is not that familiar with dll import/export and some C++ tricks either. Can some one provide some insights on the problem or which direction should I spend my time on to figure this out?
Or say, if I already have a static object like this, and I want to write another program to access it, how exactly should I do?
Please also correct me if I made any mistakes here. Thanks!
I think the keyword you need is extern, as in:
extern A *A::instance;
This says the variable A::instance is defined somewhere else, but you're telling the compiler about it so you can use it by name in this file.
__declspec(dllexport) is used when you want to export your function in a DLL. It should not be necessary as long as you're not calling the class from another DLL.
But I suspect your problem is related to using .c files and not the class specification. Try to read this by the way. It discusses dllexport in just-enough-detail Windows & C++: extern & __declspec(dllimport)
Singleton usually has a function, like
A::instance = NULL;
A * get_instance() {if (!A::instance) A::instance = new A; return A::instance;}
If you have a function like this you don't have to access A::instance directly.
And sorry, but what are you doing? Including a C++ header in a C program? Does it even compiles?
Personally I usually hide the instance in the .cpp file in an anonymous namespace. Then I provide a getInstance() function that returns a pointer or reference to it and I dllExport that function.
If you want to enforce things you can make the constructors for A private and make getInstance a friend.