I have a C++ windows application which is composed of several DLLs.
I want to have some sort of a pool from which I'll get objects, but in a way that this pool
would be available in all the DLLs.
So I put it in a "Common" dll which everbody has access to and defined it in a header file like so:
static Pool globalPool;
I do have access from every dll but this pool is created many many times.
I think it happens in each of my DLLs and in each File which include the header file with the definition.
How can I do it properly?
thanks :)
A static declaration of an object makes the object local to the compilation unit.
By using static you're creating a globalPool object (variable) in every compilation unit where you include the header.
But the way to do what you want is not to just remove the static.
Instead define a function providing access to your pool (e.g. a reference to it), and export that function or set of functions from the pool DLL.
Or better -- much better -- forget the idea. It's a generally bad idea. However, if you really want to do it, and can't see any alternative, then above is how to do it.
And if you do that, perhaps think about thread safety.
And perhaps be aware that dynamic loading of Windows DLLs does not work well with compiler support for thread local variables.
Cheers & hth.,
In the header file you need
extern Pool globalPool;
Then in a .cpp file in the Common dll, you need
Pool globalPool;
The extern declaration will put it in the namespace of including modules, and the linker will resolve it to the object in the common dll.
You'll want a header file that looks something like this:
// Common.h
#pragma once
#ifdef COMMON_BUILD
// When building Common.dll, want to export the definition of Pool
#define COMMON_EXPORT __declspec(dllexport)
#else
// When using Common.dll, want to import the definition of Pool
#define COMMON_EXPORT __declspec(dllimport)
#endif
// Declarations of shared globals
struct COMMON_EXPORT Pool {
static int data1;
static int data2;
};
(For more about the dllimport and dllexport stuff, see http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx and http://msdn.microsoft.com/en-us/library/81h27t8c.aspx)
Then in your DLL's build, you will want a source file like this:
// Common.cpp
#define COMMON_BUILD
#include "Common.h"
int Pool::data1 = 0;
int Pool::data2 = 0;
Then, all the DLLs and EXEs that use it should "#include Common.h" and link with the Common DLL, and then they can use Pool::data1, etc.
Related
I have a C++ file that outputs a string. How can I pass the string value to another file using a dll?
Code:
file name "importedfilewithvariable.h"
#include <string>
int main(){
std::string texttosend = "Hello World";
}
File importing variable
#include <iostream>
#include importedfilewithvariable.h
int main(){
std::cout << texttosend;
}
Sharing a single C++ variable through a DLL (dynamic-link library) can be done by using the extern keyword. The extern keyword is used to indicate that a variable is defined in another file or library.
Here is an example of how you can share a single C++ variable through a DLL:
Declare the variable in a header file (e.g. shared_variable.h) using the extern keyword.
#ifndef SHARED_VARIABLE_H
#define SHARED_VARIABLE_H
extern int shared_variable;
#endif
Define the variable in one of the source files of the DLL project (e.g. dll_source.cpp) and use the __declspec(dllexport) attribute to export it.
#include "shared_variable.h"
__declspec(dllexport) int shared_variable = 0;
In the application that uses the DLL, include the header file and use the __declspec(dllimport) attribute to import the variable.
#include "shared_variable.h"
__declspec(dllimport) extern int shared_variable;
Now, the variable can be accessed and modified from both the DLL and the application.
It's worth noting that this approach only works for variables, it can't be used to share function or classes across different modules. Also, it's important to keep in mind that this approach may have thread-safety issues, and it's better to use a more robust mechanism such as synchronization objects or inter-process communication (IPC) to share variables between different modules.
Another way to share a single C++ variable through a DLL is to use a Singleton design pattern, which allows to have a single instance of a class that can be accessed by any module that imports the DLL.
I'm reading the Dear ImGui API, and i'm wondering what does it mean to add a pre-processor variable (here IMGUI_API) before the function declaration like this :
#ifndef IMGUI_API
#define IMGUI_API
#endif
...
namespace ImGui
{
...
IMGUI_API float GetWindowWidth();
...
};
Thanks in advance !
Like Hans Passant said - it won't always be empty.
One of the main properties of dynamic shared objects (and DLLs in Windows) is that the internal symbols of the library are not exposed to the user. In GCC, this is done by specifying the default symbol visibility to "hidden" on the command line when building the library. However, this has the undesirable effect of making all symbols, including the ones you want users to call, hidden, which makes your library effectively useless.
GCC provides a way to manually control visibility - __attribute__((visibility("default"))). This marks a function as having default visibility, meaning it will be exposed by the DSO. This attribute is specified before the function declaration.
This creates a new problem - the users of your library don't need/want this attribute specified on your library functions when they include your header file. When your header is included by the user, these definitions should be removed, leaving just a bare function declaration.
There's two ways to solve this - have two copies of your header, or use the preprocessor to change the code before compilation. Most (almost all) library programmers choose the latter, as keeping two copies of the same file synced is very difficult.
The way the writers of ImGui have implemented the latter option is rather elegant - rather than defining their API marker inline, like so:
#ifdef IMGUI_API_BUILD
#define IMGUI_API __attribute__((visibility("default")))
#else
#define IMGUI_API
#endif
They've defined it as follows:
#ifndef IMGUI_API
#define IMGUI_API
#endif
This has the effect of defining the symbol to a default value if it hasn't been overridden.
The genius of this is actually in the compilation process - by specifying the definition of IMGUI_API on the command line, they can change the behavior of the code without exposing elements of their build process to the world.
All they have to do is add -D IMGUI_API=__attribute((visibility("default"))) to the compiler command line and the header file magically marks every API function as being exported from the shared object.
In fact, they can change the definition to any value they want without exposing that detail in the header file used by other programmers in this way. Debug information, additional function options, specifying hot/cold path info... all of this can be specified on the command line without needing to place that information into the header file.
Edit:
Looking through their code now, it seems they haven't realized this, and have created a very powerful shared-library solution for Linux without meaning to. Despite that, all of the above is still valid - other libraries can do the same thing.
I have a number of C++ projects in my solution that were written by other teams before I started working on my UWP app, and all of these projects use std::strings. So, to ease the communication between the other projects and my WinRT modules, I wrote some string conversion functions to go from std::strings to Platform::Strings and vice versa.
I'm in the process of converting my UWP codebase into WinRT modules and I'm coming across a recurring problem: because WinRT modules don't allow you to have classes or functions with public native types, I am unable to have my string functions publicly accessible. A private, protected, or internal declaration is fine for passing around native types, just not public.
Many of my modules need to communicate down into the native C++ code and I don't want to have to redefine my string functions again and again for each individual file that needs a std::string.
Is there anything I can do so I can reuse my string functions across WinRT modules? Has anyone else had a similar problem? Any suggestions are greatly appreciated!
Thank you
You have two options.
Make those functions inline, and define all of them in a header file. Then, include the header file everywhere you want to consume them. This is a more straightforward solution without requiring you to mess with your build system.
You can compile those functions into one of your DLLs, and import them to other ones. Let's call the DLL where you put your functions in "StringModule.dll". You'll need to put those functions in a .cpp/.h header file pair, then compile that .cpp file into StringModule.dll. Then, annotate your functions with a define that evaluates to __declspec(dllexport) when building StringModule.dll, and __declspec(dllimport) when building all the other DLLs. For instance:
#ifndef BUILDING_STRING_CONVERSIONS_DLL // This should be defined to 1 when building StringModule.dll
#define BUILDING_STRING_CONVERSIONS_DLL 0
#endif
#if BUILDING_STRING_CONVERSIONS_DLL
#define MY_STRING_API __declspec(dllexport)
#else
#define MY_STRING_API __declspec(dllimport)
#endif
namespace MyStringFunctions
{
MY_STRING_API Platform::String^ ConvertStdStringToPlatformString(const std::string& str);
MY_STRING_API std::string ConvertPlatformStringToStdString(Platform::String^ str);
}
When you build StringModule.dll, there will be StringModule.lib file created next to it. You'll have to pass its path to the linker as an argument when building all the DLLs that consume your string functions. In all the places where you want to use your DLL, just include that header file and use them as usual.
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.
I have a (big and complex) C++ program with its own classes and methods.(obviously)
I would like to load at runtime a dll. From the main program i want to call a function inside the dll passing a class instance , and this function will use the method of this class.
In pseudo code
Main program:
class MyClass{
myattr1();
myattr2();
mymethod1();
mymethod2();
}
void main(){
MyClass* object = &(new MyClass())
handle_of_the_dll = *some function that load the dll*
dllfunc = getfunc(handle_of_the_dll, "interesting_function")
dllfunc(object)
[...etc...]
and the dll
#ifdef __cplusplus
extern C {
#endif
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
#include all the needed headers from main program, where the class is defined
EXPORT void interesting_functionn(MyClass object){
object.mymethod1();
}
#ifdef __cplusplus
}
#endif
Is this valid/doable/right?
EDIT:
i know that this would be a poor design for a general program, but this method is intended to give the users the ability to use their custom dll that can access the api of the main program. Something like Cpython modules
It is valid and doable. Generate a sample DLL in visual C++ and the code will have all the bases covered. Replace the static linking in the client with LoadLibrary and GetProcAdress.
Name mangling could be an issue, DependencyWalker will help you there.
Keep a low profile with emory management. For example, if you use a memory manager on one side but not on the other, your begging for trouble.
I'd say it's possible, but with all due respect, it looks like bad design to me. There is a circular dependency between the main program and the dll: the program calls functions from the dll, and viceversa. In an ideal design, the main program would consume some dll functions, and the dll wouldn't know anything about the main program, or in general, about its clients.
Perhaps you should isolate the functions from the main program that the dll needs to use in a common dll or static lib which both the program and dll use.
As long as the methods are declared virtual and you pass the object by reference or pointer there should be no problems. If however you want to access non-virtual methods of the class you will need to put it's implementation in a separate DLL.