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.
Related
I always wondered what is the real use case of __declspec(dllimport). I know that building a shared library requires to export its symbols using __declspec(dllexport) and then the user of the library use theses symbols as __declspec(dllimport).
Then, you should build your shared library with a special define which enables dllexport and if the flag is not set, the symbols are defined as dllimport.
However, I never used dllimport at all and it just works.
I have two projects:
ImportExport
Has a small Util class which is build with EXPORTING defined
Util.h:
#ifndef _UTIL_H_
#define _UTIL_H_
#if defined(EXPORTING)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT // I should use __declspec(dllimport) but client will try out
#endif
class EXPORT Util {
public:
static void test();
};
#endif // !_UTIL_H_
Then in the source file Util.cpp:
#include <iostream>
#include "Util.h"
void Util::test()
{
std::cout << "Testing..." << std::endl;
}
Nothing much complicated, as you can see, when the user will use this file, EXPORT will not be defined at all (where it should be defined to dllimport).
The client exe
Main.cpp:
#include <Util.h>
int main(void)
{
Util::test();
return 0;
}
Links to ImportExport.lib without any define set, just works. No undefined reference.
I wonder why is the use case of dllimport? Is it present for backward compatibility?
Note: All the code presented was tested on VisualStudio 2012 Express.
Raymond Chen describes the dll import mechanism in detail in this series; summing it up, dllimport for functions is essentially a performance optimization.
If you don't mark a function as dllimport the compiler and the linker will treat it as a normal function, with "static" function calls resolving it to the stub found in the import library. The stub actually has to fetch the address of the imported function from the IAT and perform a jmp there (i.e. it has to somehow convert the direct call that the compiler generated to an indirect call), so there's some performance penalty in this two-step process.
dllimport, instead, tells the compiler that it has to generate code for an indirect call via the IAT right from the compilation phase. This reduces the indirections and allows the compiler to cache (locally to the function) the target function address.
Notice that, as MSDN says, you can omit dllimport only for functions; for data it's always necessary, because there's not a mechanism available for the linker to rework the direct accesses to variables generated by the compiler in indirect ones.
(all this was particularly relevant in times of "classical" linkers; nowadays, with link-time code generation enabled, all these points can be worked around by simply letting the linker fully generate the function calls/data accesses)
i'm using VS2010, and i am designing a MVC application.
Say i have "Project 1" and "Project 2" in a solution. The need to be compiled in that order, P1 compiles to a DLL, P2 to an Exe file that dynamically uses the DLL. P2 declares a view interface. Both projects have a view class that implements the interface (a class with pure virtual methods).
The problem now is, that i cannot include the header file of the interface in P1, because the linker would say then that he cannot resolve this external symbol. Which is of course right, because it is compiled later in P2.
So what i did is, i added the include folder for P2 to P1 and included the interface.cpp in P1 instead of the header file.
It works, but i don't think this is what i am supposed to do. Or isn't it? The interface is obviously compiled twice, once in each project.
I don't want to move the interface to P1, what would solve the problem. Just assume, i don't want that.
Thanks for input.
edit: code snippet:
Project1:
View1.hpp // nothing special
View1.cpp:
#include ViewInterface.cpp
View1::View1(int x) : ViewInterface(int x)
Project2:
ViewInterface.hpp:
#ifdef EXP
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
class ViewInterface : SomeOtherClass, AnotherClass
{
virtual void DECLDIR show(void) const = 0;
virtual void DECLDIR hide(void) const = 0;
}
ViewInterface.cpp:
ViewInterface::ViewInterface(int x) : SomeOtherClass(int x), AnotherClass(int x)
View2.hpp // nothing special
View2.cpp:
#define EXP
#include ViewInterface.h
View2::View2(int x) : ViewInterface(int x)
In order for the executable to use classes from the DLL, you need to make sure that they're exported properly. When you compile the DLL, you mark the class with __declspec(dllexport), and when you compile the executable, you instead mark the class with __declspec(dllimport). Typically this is done with a macro like so:
// In your DLL's header file
#ifdef COMPILING_MY_DLL
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT __declspec(dllimport)
#endif
class MY_EXPORT MyClass
{
...
};
Then, in only your DLL project, you define the macro COMPILING_MY_DLL.
I don't want to move the interface to P1, what would solve the
problem. Just assume, i don't want that.
Then move it to a third entity.
You have to decide what's more important to you. If you want a clean solution, then either move the interface definition to the DLL (P1), or to something that both the DLL and the EXE can use - let's call it "P0". P0 doesn't even have to be something that's compiled - a simple header file in it's own directory with everything defined inline will do just fine. My preferred choice would be to have P0 be a DLL though.
That is the only clean solution. The following "solutions" are really just hacks that I describe for sake of completeness.
If you really want the "dirty" solution, then do the same, with the only difference that you leave the header file defining the interface in the application-source-folder.
And if you want it ultra-dirty, then include the .cpp file when building the DLL like you suggested. It will also work... it's just really yuck.
Of course you do have to be aware of some things. E.g. the "interface" should not have any static data members, and no function in the "interface" should have function local statics. Because if they do, then those static variables will be instantiated twice - once in the DLL and once in the EXE. Also since all code will be compiled into both projects, you have to re-compile both projects if you want to change anything. (The code being duplicated in the DLL and EXE isn't a problem as long as they were compiled from the same code.)
Those limitations of course also apply if you choose the "P0 = just a header file" solution.
And finally there's the really really bad super-dirty solution: implement the interface in the EXE, dllexport it from the EXE and dllimport it in the DLL (yes, that can be done!). Downside is that you would have to do a special EXE build that only builds the import-library for the EXE (which can be done without having the import library for the DLL). With the import library for the EXE you can then build the DLL, and with the import library for the DLL you can then build the EXE itself.
That way the "interface" could even have static data members, and if you change only the code (i.e. no changes in the header-files) then you would only have to re-compile the EXE.
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.
Created basic C++ DLL and exported names using Module Definition file (MyDLL.def).
After compilation I check the exported function names using dumpbin.exe
I expect to see:
SomeFunction
but I see this instead:
SomeFunction = SomeFunction###23mangledstuff#####
Why?
The exported function appears undecorated (especially compared to not using the Module Def file), but what's up with the other stuff?
If I use dumpbin.exe against a DLL from any commercial application, you get the clean:
SomeFunction
and nothing else...
I also tried removing the Module Definition and exporting the names using the "C" style of export, namely:
extern "C" void __declspec(dllexport) SomeFunction();
(Simply using "extern "C" did not create an exported function)
However, this still creates the same output, namely:
SomeFunction = SomeFunction###23mangledstuff#####
I also tried the #define dllexport __declspec(dllexport) option and created a LIB with no problem. However, I don't want to have to provide a LIB file to people using the DLL in their C# application.
It's a plain vanilla C++ DLL (unmanaged code), compiled with C++ nothing but a simple header and code. Without Module Def I get mangled exported functions (I can create a static library and use the LIB no problem. I'm trying to avoid that). If I use extern "C" __declspec(dllexport) OR a Module Definition I get what appears to be an undecorated function name... the only problem is that it is followed by an "=" and what looks like a decorated version of the function. I want to get rid of the stuff after the "=" - or at least understand why it is there.
As it stands, I'm pretty certain that I can call the function from C# using a P/Invoke... I just want to avoid that junk at the end of the "=".
I'm open to suggestions on how to change the project/compiler settings, but I just used the standard Visual Studio DLL template - nothing special.
Instead of using .def file just insert pragma comment like this
#pragma comment(linker, "/EXPORT:SomeFunction=_SomeFunction###23mangledstuff#####")
Edit: Or even easier: Inside the body of the function use
#pragma comment(linker, "/EXPORT:" __FUNCTION__"=" __FUNCDNAME__)
. . . if you have troubles finding the decorated function name. This last pragma can be further reduced with a simple macro definition.
You can get what you want by turning off debug info generation. Project + Properties, Linker, Debugging, Generate Debug Info = No.
Naturally, you only want to do this for the Release build. Where the option is already set that way.
You have to declare the functions as extern "C" if you don't want their names to be mangled.
From experience, be careful if you use __stdcall in your function signature. With __stdcall, the name will remain mangled to some extent (you will find out quickly enough). Apparently, there are two levels of mangling, one the extern "C" deals with at the C++ level, but it does not deal with another level of name mangling caused by __stdcall. The extra mangling is apparently relevant to overloading -- but I am not certain of that.
Even without the mangling, the 32-bit and 64-bit builds name exports differently, even with extern "C". Check it out with DEPENDS.EXE.
This can mean BIG trouble to any client that does a LoadLibrary+GetProcAdress to access your function.
So, on top of all the others use a Module Definition File as follows:
LIBRARY MYDLL
EXPORTS
myFunction=myFunction
Yeap, it's a bit of a pain to maintain, but then how many exported functions do you write a day?
Moreover, I usually change the macros like shown below, since my DLLs export functions not C++ classes and I want them to be callable by most programming environments:
#ifdef WTS_EXPORTS
#define WTS_API(ReturnType) extern "C" __declspec(dllexport) ReturnType WINAPI
#else
#define WTS_API(ReturnType) extern "C" __declspec(dllimport) ReturnType WINAPI
#endif
WTS_API(int) fnWTS(void);
The last line used to confuse VisualAssistX a couple of years ago, I don't know if it properly digests it now :-)
Sorry for replying to an old thread, but what has been marked as the answer did not work for me.
As a number of people have pointed out, the extern "C" decoration is important. Changing the "Project / Properties / Linker / Debugging / Generate debug info" setting made absolutely no difference to the mangled names being generated for me in either Debug or Release build mode.
Setup: VS2005 compiling a Visual C++ Class Library project. I was checking the compiled .dll output with Microsoft's Dependency Walker tool.
Here is an example recipe that worked for me...
In project.h:
#define DllExport extern "C" __declspec( dllexport )
DllExport bool API_Init();
DllExport bool API_Shutdown();
In project.cpp:
#include "project.h"
bool API_Init()
{
return true;
}
bool API_Shutdown()
{
return true;
}
Then being called from C# managed code, class.cs:
using System.Runtime.Interopservices;
namespace Foo
{
public class Project
{
[DllImport("project.dll")]
public static extern bool API_Init();
[DllImport("project.dll")]
public static extern bool API_Shutdown();
}
}
Doing the above prevented the mangled names in both Debug and Release mode, regardless of the Generate debug info setting. Good luck.
I know how many times I've tried forcing function names using code and #pragma's.
And I always end with exactly same thing, using Module-Definition File (*.def) at the end.
And here is the reason:
//---------------------------------------------------------------------------------------------------
// Test cases built using VC2010 - Win32 - Debug / Release << doesn't matter
//---------------------------------------------------------------------------------------------------
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = Yes (/DEBUG)
// || (or, also doesn't matter)
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = No + delete PDB file!
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> _SetCallback#4
__declspec(dllexport) void SetCallback(LPCALLBACK function);
> ?SetCallback##YAXP6AXHPADPAX#Z#Z
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> ?SetCallback##YGXP6GXHPADPAX#Z#Z
//---------------------------------------------------------------------------------------------------
// this also big is nonsense cause as soon you change your calling convention or add / remove
// extern "C" code won't link anymore.
// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback=SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=_SetCallback#4")
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback##YAXP6AXHPADPAX#Z#Z")
__declspec(dllexport) void SetCallback(LPCALLBACK function);
// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback##YGXP6GXHPADPAX#Z#Z")
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
//---------------------------------------------------------------------------------------------------
// So far only repetable case is using Module-Definition File (*.def) in all possible cases:
EXPORTS
SetCallback
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback
__declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback
// And by far this is most acceptable as it will reproduce exactly same exported function name
// using most common compilers. Header is dictating calling convention so not much trouble for
// other sw/ppl trying to build Interop or similar.
I wonder why no one did this, it took me only 10 mins to test all cases.
the SomeFunction###23mangledstuff##### is mangled to give the types and class of the C++ function. The simple exports are functions that are callable from C i.e. are written in C or else are declared extern "C' in C++ code. If is you want a simple interface you have to make the functions you export be use just C types and make them non member functions in the global namespace.
Basically, when you use functions in C++, parts of their names now include their signature and suchlike, in order to facilitate language features like overloading.
If you write a DLL using __declspec(dllexport), then it should also produce a lib. Link to that lib, and you will automatically be linked and the functions registered by the CRT at start-up time (if you remembered to change all your imports to exports). You don't need to know about name mangling if you use this system.
In case it wasn't clear from the hundreds of lines of waffle on the subject of mangled exports. Here's my 2c worth :)
After creating a project called Win32Project2 using VS 2012 and choosing export all symbols in the wizard. You should have 2 files called Win32Project2.cpp and Win32project2.h
Both of those will reference an example exportable variable and an example exported function.
In Win32Project2.h you will have the following:
#ifdef WIN32PROJECT2_EXPORTS
#define WIN32PROJECT2_API __declspec(dllexport)
#else
#define WIN32PROJECT2_API __declspec(dllimport)
#endif
extern WIN32PROJECT2_API int nWin32Project2;
WIN32PROJECT2_API int fnWin32Project2(void);
To unmangle CHANGE the last two lines to extern "C" declarations to:
extern "C" WIN32PROJECT2_API int nWin32Project2;
extern "C" WIN32PROJECT2_API int fnWin32Project2(void);
In Win32Project2.cpp you will also have the following default definitions:
// This is an example of an exported variable
WIN32PROJECT2_API int nWin32Project2=0;
// This is an example of an exported function.
WIN32PROJECT2_API int fnWin32Project2(void)
{
return 42;
}
To unmangle CHANGE THESE TO:
// This is an example of an exported variable
extern "C" WIN32PROJECT2_API int nWin32Project2=0;
// This is an example of an exported function.
extern "C" WIN32PROJECT2_API int fnWin32Project2(void)
{
return 42;
}
Essentially you must use the extern "C" prefix in front of declarations in order to force the linker to produce unmangled C like names.
If you prefer to use mangled names for that bit of extra obfuscation (in case the mangling info is useful to someone somehow) use "dumpbin /exports Win32Project2.dll" from a VC command line to lookup the actual reference names. It will have the form "?fnWind32Project2#[param bytes]#[other info] . There are also other DLL viewing tools around if running a VC command shell doesn't float your boat.
Exactly why MS doesn't default to this convention is a mystery. The actual mangling information means something (like parameter size in bytes and more) which might be useful for validation and debugging but is otherwise guff.
To import the DLL function above into C# project (in this case a basic C# windows application with a form on it containing the button "button1") here's some sample code:
using System.Runtime.InteropServices;
namespace AudioRecApp
{
public partial class Form1 : Form
{
[ DllImport("c:\\Projects\test\Debug\Win32Projects2.dll")]
public static extern int fnWin32Project2();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int value;
value = fnWin32Project2();
}
}
}
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.