I have a problem concerning the export/import of a global variable in a DLL. I have a static library which contains a global variable such as :
In the header :
#ifdef _ENGINE_EXPORTS
extern __declspec(dllexport) Globals data;
#else
extern __declspec(dllimport) Globals data;
#endif
In the source file :
#ifdef _ENGINE_EXPORTS
__declspec(dllexport) Globals data;
#else
__declspec(dllimport) Globals data;
#endif
This global variable is exported in a DLL which links against this static library. I can see the exported symbol using DLL Export Viewer. My problem is that I want to use this global variable in another DLL and that they share the data. Right now, the same symbol is also exported in the DLL (I can see it too) and thus they have different addresses. I would like that in this other DLL, the global variable is the same as in the first DLL.
Thanks.
The following MSDN documentation topic describes how to place data in a shared segement:
How do I share data in my DLL with an application or with other DLLs?
In the project, one DLL is at the root of all the others so I exported the symbol in this one and it seemed to work.
From your description I understand that you have two different DLLs which both export the global variable data.
When a DLL exports a variable this DLL allocates memory to the content of this variable and offers to other SW parts in the same process (e.g. to the application which loaded the DLL) to use this memory via the variable name. So if you export data from both DLLs both DLLs allocate memory and both offer in their context the variable name data (you can imagine this as two variables with the same name, but in different namespaces).
What you want to do, is that one DLL exports the data and the other DLL imports this variable. With this (dllimport) you declare the variable name without defining (and thus without allocating memory for) it.
So taken this static library from you question as static.hpp, static.cpp and static.lib:
you have dll_1.cpp (linked against static.lib)
#define _ENGINE_EXPORTS (1)
#include "static.h"
__declspec(dllexport) int getAdrAsInt_1()
{
return (int)&data;
}
and dll_2.cpp (linked against the "import library" of dll_1, see here )
// here without _ENGINE_EXPORTS to use dllimport instead of dllexport
#include "static.h"
__declspec(dllexport) int getAdrAsInt_2()
{
return (int)&data;
}
Another way to access data in dll_1 from dll_2 would be to use from dll_2, GetProcAddress. But then you need the HMODULE from the LoadLibrary-call to load dll_1.
BTW: As I understand your situation "How do I share data in my DLL with an application or with other DLLs?" is not applicable, because it describe a complete different scenario.
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 know how to use explicit linking for a dll that doesn't contain class but how can link a dll contains class, example:
class math{
public:
int sum(int,int);
};
to load it:
typedef int(*func)(int,int);
int main{
HINSTANCE hDLL; // Handle to DLL
hDLL = LoadLibrary("math.dll");
func add=(func)GetProcAddress(hDLL, "sum");
add(4,5);
return 0;
}
if i do this it stop working and exit the program , if i remove the class it works
GetProcAddress can load up exported symbols form the DLL, provided you called it with the correct name.
In your case the function is not exported in the first place. And if it was, it is surely not called "sum" but some gibberish with 20-40 characters.
For using DLLs with C++ code you'll want to drop the GetProcAddress way entirely, and rely only on the implib that maps the names fine.
For that you add __declspec(dllexport) to the class (preferably with dllimport at the client), and add your DLL project as project reference. Alternatively add the .lib that was created along with the DLL to the client project.
C++ compilers use name mangling to uniquely distinguish identifiers in your program. This mangling causes the name to be significantly different than the plain identifiers you use in your program. Because of this using GetProcAddress is typically impractical for accessing code written in C++ that resides in a DLL. Instead I recommend using __declspec(dllexport) and __declspec(dllimport) to provide painless access to the code residing in your DLL.
In your DLL's project you will want to add a preprocessor definition with a name such as "EXPORT_CLASSES" or one unique to the DLL. This will be used by your DLL and program to determine if a particular declaration should be exported by the DLL or imported by the program.
dllstuff.h
#ifdef EXPORT_CLASSES
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif
You will then change the class declaration for math to use this. When the DLL is compiled IMPORT_EXPORT will be equal to __declspec(dllexport) and will instruct the compiler and linker that the definitions for this class should be made publicly available (ie. through the DLL's export table).
mathclass.h
#include "dllstuff.h"
class IMPORT_EXPORT math
{
public:
int sum(int, int);
};
Now all you have to do in your main application is include the mathclass.h any time you want to use the math class. You can now instantiate an instance of math and access it's member functions.
#include "mathclass.h"
int main()
{
math m;
int result = m.sum(1, 2);
}
This of course is just a basic description of the process. There are plenty of articles floating around the web (including SO) with provide much more detailed information.
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.
I am using Microsoft Visual C++ 2010 Express, on Windows XP.
I have one application that produces a DLL, a header file in this application also declares a pointer to a BUFFER as an extern.
To register this DLL with the system, I drag it onto the regsvr32.exe icon in the system32 folder.
I have another application that tests the use of this DLL, by initialising and calling functions from it. This application accesses the same BUFFER as the DLL, by using this extern declaration.
At first, when I used the Visual Studio debugger to debug the test application, I could see the contents of the extern BUFFER from the loaded DLL. However, after repeatedly debugging this application, now the BUFFER does not display its memory address, just "0x0000000", so I can't view the data.
Does anyone know why this might be? I can't understand why it used to work, but now doesn't. I haven't changed any aspect of this part of the source code, at all.
Is it OK to access the BUFFER in the DLL by using an extern pointer like this, or is there
a better way?
Thanks for your help.
In C++ extern means, that variable is declared in another *.cpp (translation unit).
Example:
myfile1.cpp:
int globalVariable = 0;
myfile2.cpp:
extern int globalVariable; //same variable, because of extern
If you need to export from dll, you must use dllexport (in library) and dllimport (in library consumer) for functions and variables, e.g.:
mylibrary.cpp:
__declspec(dllexport) int myGlobalExportingVariable = 0;
myprogram.cpp:
__declspec(dllimport) int myGlobalExportingVariable;
Of course, in real world, you would probably use something like this:
mylibrary.hpp:
#ifdef MYLIBRARY
#define MYLIBRARY_ITEM __declspec(dllexport)
#else
#define MYLIBRARY_ITEM __declspec(dllimport)
#endif
MYLIBRARY_ITEM void func1();
MYLIBRARY_ITEM int variable0;
MYLIBRARY_ITEM float func2();
//...
And you #include this header in both mylibrary.cpp and myprogram.cpp; don't forget to define MYLIBRARY macro in your project settings (C++ -> Preprocessor -> Preprocessor definitions).
By the way: as pointed in comment by PiotrLegnica, registering your dll library with regsvr32.exe is pointless unless you use technology COM (component object model).
When you declare a variable with extern then it’s mean only declare it but not define it( no memory allocation for that variable) because its define it other place.
You declare the variable in your cpp file with dll codes. In header make it as extern with dllexport/import and now use it.
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.