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.
Related
I am currently working on a project with some old poorly documented code, and am trying to navigate my way through the various .h files that they have provided complete documentation on the use of all of the functions contained (the definitions are held in .lib and .dll files). One of the .h files has functions the are not only declared, but defined with either simple return statements or empty statements as such
class DLL ExampleLibraryClass {
public:
int exampleGetValue() {return 0;}
void exampleSetValue(Type val) {;}
void exampleActionFxn() {;}
};
These would be functions that I expect to return current variable states or perform certain actions, which is why this puzzles me.
Additionally:
I have used Dependency Walker and found that each function does have a matching definition in a dll.
The Keyword DLL has been defined with
#ifndef _PWSDLL_
# define _PWSDLL_
# define WINCALL _stdcall
# ifdef _USRDLL
# define DLL __declspec(dllexport)
# else
# define DLL __declspec(dllimport)
# endif
#endif
_USRDLL is not defined and therefore DLL is defined as __declspec(dllimport)
My question revolves less about the apparent effect of the empty definitions (which do nothing I suppose, and have already been discussed on SO) and more about why the .h file has been written this way and how to utilize the file. Is this a common or known practice? Will the linker still look for definitions to the function in my linked libraries? Are there other pieces of code that I should look for for more clues? Or perhaps in the broadest sense, how should I respond to this?
Many thanks, and please let me know if you need more information to address this, I am unsure what exactly is important in this matter.
EDIT: Added forgotten return types in example code.
EDIT: Added note about DLL definition.
One scenario where you put this code to some use would be to override the functions. These functions hold some default code and could be overridden later.
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).
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.
Ok, so I know portability is not the strong point of C++, but I have to get my code running on both Mac&Windows. I've come up with a solution, but it's not perfect, and I'm interested to see if there is someone out there who can suggest a better one.
I need to us a class hierarchy in several DLLs/bundles - e.g., I have an abstract base class BaseClass; and I scan a given directory for DLLs, and for each DLL, I look for the factory method BaseClass* CreateObject(); - which returns a "BaseClass". I have a "shared header file" that I include both in the "main executable" & in the DLLs, that declares the BaseClass like this
#ifdef _MAC
#define DECLSPEC
#else
#ifdef COMPILING_DLL
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
#endif
class DECLSPEC BaseClass{
[.. base "interface" declaration .. ]
}
And then, in my DLL, I would typically include the BaseClass declaration, and declare my own "concrete" class:
class MyDllClass:public BaseClass{
[.. actual DLL class definition/implementation here goes here ...]
}
So far, so good. Now for some reason, I need to differentiate in my main executable between two different kinds of BaseObjects - say I have a DescriptionClass and an ActionClass, both of which are BaseClass, but have a slightly different interface. My fist implementation was to simply do modify the "shared header" and add:
class DECLSPEC DescriptionClass{
[.. base "Description interface" declaration .. ]
}
class DECLSPEC ActionClass{
[.. base "Action interface" declaration .. ]
}
Then my DLL would become:
class MyDllClass:public ActionClass /* or DescriptionClass, depending on case*/ {
[.. actual DLL class definition/implementation here goes here ...]
}
And in my main executable, I would use it like this:
BaseClass* obj = CreateObjectFromDLL("path_to_dll");
ActionClass* action_obj = dynamic_cast<ActionClass*>(obj);
if(action_obj){
// Do the stuff that is relevant for Action objects
}
DescriptionClass* description_obj = dynamic_cast<ActionClass*>(obj);
if(description_obj){
// Do the stuff that is relevant for Description objects
}
And herein lies the problem: although it works on Windows with Visual Studio (probably due to the MS declspec extension), it fails on Mac (not sure now if it fails on Debug, but I'm sure it fails on release) when compiled with GCC. The reason is simple, even if not immediately obvious: the executable & the dynamic library are compiled separately. Although they both include the declaration of BaseClass, ActionClass, DescriptionClass - these classes are not the same, they are just "identical copies" that are present in the binary and the DLL. So actually, what I'm creating in the DLL is a dll'BaseClass* , which happens to have the same memory layout with main'Baseclass*, so the pointers are compatible, so when I pass the pointer from DLL to EXE, it all works "as expected". OTOH, when I go to a more complex class hierarchy, the vtables/RTTI of dll'ActionClass and main'ActionClass are no longer identical (although in source code they are identical), so when I try do convert (through dynamic_cast) a main'BaseClass* to a main'ActionClass* i get a null result -> because my pointer actually points to a dll'BaseClass object / dll'ActionClass object, and alghough in the DLL I can convert with no proble a "BaseClass*" into a "ActionClass*" - in the main executable, I can't convert the dll's "BaseClass*" into a "ActionClass*", due to the subtle runtime differences between the DLL's and the "main executable's" version of Action Class.
I've "fixed" this by declaring a virtual method in the BaseClass (something like "bool isActionClass()" ), so now I can differentiate... but I'm not very happy with this solution.
Is there something for GCC - e.g. some declaration similar to "__declspec" - a way to guarantee that the same class declared in "main executable" and in "dll" will be 100% compatible?
I actually found the answer to my question due to the fact that I needed to formulate it completely, and I did a better google search :)
It seems to be
__attribute__((dllimport)) // import
__attribute__((dllexport)) // export
Will try that, I thought I'd leave the question here too, in case someone else stumbles on this problem (and as a warning to people that same header file included in a "main binary" & DLL will normaly lead to different actual implementation, depending on the compiler options - unless you put the proper dllimport/export attributes on the class).
That would only work if RTTI is enabled. You, probably, get that automatically enabled in MSVC++, but gcc requires specific link switches. Look in GCC FAQ for details.