I am not that experienced in creating DLL's in MSVC++ 2010, just may be a few times as part of the learning curve. At the moment I have a very large file with about 10 different classes in it. I have to breakdown the file into multiple files and move out related classes to the same file. So before proceeding wanted to know from experienced developers about my situation.
Something like the following
// Header
namespace collections
{
classA
classB
ClassC
ClassD : ClassA,ClassB
}
// CPP
namespace collections
{
classA
{
// Implementations
}
// Rest of the classes
}
After breaking down to separate files
// ClassA.h
namespace Collections
{
ClassA
}
// ClassB.h
namespace Collections
{
ClassB
}
// Implentations etc
My main concern is the usage of dllexport/dllimport storage class attributes
Since The file will be broken up I would have to use the following
#ifdef MAKEDLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif
against the classes to export/import them. But placing these line in each header file that will be create (with one namespace "Collections"), will this have any bad implications while compiling or code generation step? I was looking around on-line and found out that people most complain about linker errors/warnings where a particular member is redefined or is not found whilst creating DLL's. This must definitely be a solved issue just that I dont know which is the best and proper way of doing it.
I need to create just one DLL in the end. I dont need to create multiple DLL's.
Any guidance or help is much appreciated.
Thank you
There is no issue to have one common header file that defines the EXPORTS macro:
mydll.h
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
And have this header file included in other header files:
ClassA.h
#include "mydll.h"
namespace Collections
{
class MYDLL_API ClassA {
// ...
}
}
ClassA.cpp
#include "ClassA.h"
// ...
ClassB.h
#include "mydll.h"
namespace Collections
{
class MYDLL_API ClassB {
// ...
}
}
... and so on. You can have all of them (header files and .cpp implementation files) in one DLL, having MYDLL_EXPORTS defined in your DLL project settings (it is automatically done by the VS2010 DLL wizard).
There is nothing weird here. You never redefine anything.
You just use the handy MYDLL_API to add a decorator to all your DLL API classes.
Related
I'm developing a DLL using Visual Studio. Currently, I have one header file: MyProject.h:
#pragma once
#ifdef MYLIBRARY_EXPORTS
#define MYLIBRARY_API __declspec(dllexport)
#else
#define MYLIBRARY_API __declspec(dllimport)
#endif
#include <map>
#include <string>
extern "C" class MYLIBRARY_API Class1
{
// some stuff here...
};
extern "C" class MYLIBRARY_API Class2
{
// some stuff here
};
I am going to be adding some more classes to the project and I would like to add separate header files for each class (please advise if I should not do that). However, eventually, I want to package all that into a single .dll and .lib in such a way that the client only needs to include a single header file. That is, the client project has #include "MyProject.h" which is essentially a collection of header files with their implmentation files. Is this possible and how can I achieve this? Thanks.
EDIT:
To be specific, what I want to do is to put Class1 in Class1.h and Class2 in Class2.h and include both of them in one master header file called MyLibrary.h so that a client only have to do #include "MyLibrary.h".
If you have several header files like A.h, B.h etc and want to give the client just Project.h that includes all, then simply include all the headers in Project.h - like so:
#ifndef MY_PROJECT_H
#define MY_PROJECT_H
#include "A.h"
#include "B.h"
#endif
Sorry ,I misunderstood what you were asking.
Yes, you can have multiple header-files that are included in your library header-file (be sure to include them with #include "...").
if you want to eliminate the need of specifying library in the linker-section (this is what I thought you were asking) ,with MSVC++ the thing you're looking for is
#pragma comment( comment-type [,"commentstring"] )
https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp
My VS2012 Solution contains several VC++ projects.
I also have many common files that need to be shared.
It's easy to share enum's and structures. I just "include" corresponding header file and that's it. I even don't need to compile my "commons" project!
But what if I need to share more complex classes that contain both .h and .cpp files, and so need to be compiled?
And the most complicated question - can I share thread-safe singleton? I want to access it from different projects from different threads (but from one process).
I guess I should use something like static or dynamic linking, but i'm not sure. Probably someone can link step-by-step tutorial to solve such problem?
I would prefer something portable as I will move entire solution to Linux later.
The projects that contain classes that you want to share should export their symbols. When you create a DLL project in Visual Studio you can give it the option to "Export" symbols and it provides some boiler-plate code for you to use.
In essence, in your libraries header file, it will give you:
// myapi.h
#if defined(MYAPIEXPORTS)
#define MYAPI __declspec(dllexport)
#else
#define MYAPI __declspec(dllimport)
#endif
'MYAPIEXPORTS' is provided by the wizard, but it's a compiler preprocessor directive ONLY on the library itself. Hence when you compile the library, MYAPI is for exporting and when the header file is included in your other projects, it will be for importing.
Now let's look at a class you want to share.
// myclass.h
class MYAPI MyClass
{
public:
MyClass();
~MyClass();
};
// myclass.cpp
#include "myClass.h"
MyClass::MyClass() { /* ... */ };
MyClass::~MyClass() { /* .... */ }
Your other projects then need to link with the resulting .lib file that is generated.
Note that if you have a template<> class contained entirely within a header file, you do not export it. That will behave like your enums and typedefs.
To answer the second part of your question, yes a singleton defined in your library will be accessible to the main project also.
I am having trouble with a dll I am writing in C++. There is some very strange behavior going on that I have not been able to solve on my own.
It's hard to describe exactly what's going on, but I will try my best. Basically I have a class in my DLL with a single private property and a public constructor. When I initialize this class and then exit the program I get an error.
"Run-Time Check Failure #2 - Stack around the variable 'test' was
corrupted"
I have 2 projects here:
The DLL named "testdll".
The console test program named "test".
I have boiled this error down to its simplest reproducible form to try and narrow down the possible causes, below you will find my code.
Project "testdll", file testdll.h:
#include <string>
class testdll
{
public:
__declspec(dllexport) testdll(); // Empty but same error if prams are used.
private:
std::string _var;
};
Project "testdll", file testdll.cpp:
#include "testdll.h"
testdll::testdll()
{
}
Project "test", file testdll.h:
#include <string>
class testdll
{
public:
__declspec(dllimport) testdll();
};
Project "test", file stdafx.h:
#pragma once
#include "targetver.h"
#include <tchar.h>
Project "test", file test.cpp:
#include "stdafx.h"
#include "testdll.h"
int _tmain(int argc, _TCHAR* argv[])
{
testdll test;
return 0;
}
If you want I can send you the Visual C++ 2010 solution file, in the archive format of your choice. Please help! I have no idea what's going on.
Optional Information:
Language (or Software): C++
Already Tried:
Deleting the constructor definition, which works but is not a usable solution, nor does it explain the problem. Also making all of my private properties into pointers works, however I should not have to do this.
You are using two header files, they don't declare the same class. One has a std::string member, the other doesn't. That's very very bad, the compiler doesn't reserve enough space for the object on the stack frame. Which is what the runtime error is telling you. Very nice feature btw, this kind of mistake is incredibly hard to diagnose otherwise.
You probably got into this pickle because you only applied __declspec(dllexport) to the constructor instead of the entire class. You'll need to write the header file so it can be used by both your dll project and your exe project. That should look like this:
#undef DLLEXPORT
#ifdef BUILDING_MYDLL
# define DLLEXPORT __declspec(dllexport)
#else
# define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT testdll
{
public:
testdll();
private:
std::string _var;
};
Right-click your DLL project, Properties, C/C++, Preprocessor, Preprocessor Definitions. Append BUILDING_MYDLL
And delete the testdll.h file in your exe project directory. Set the C/C++, General, Additional Include Directories setting so the compiler can find the header in the testdll project directory (like ..\testdll)
Exporting classes and class members from a DLL is very VERY fragile, as you have just discovered. If the library and client don't both use the exact same class layout, which depends on all kinds of compiler settings, things fail horribly.
In your case, you're probably using incompatible versions of std::string inside class testdll. Maybe one is compiled for debug and one for release. Or one is using the static runtime library and the other the DLL runtime. Who can say?
Anyway, as soon as you export C++ features from a DLL, you lock yourself in to that compiler version and settings. It's a maintenance nightmare.
Use v-table-only base classes or C-compatible wrapper functions.
I am using dev c++. also i am getting assistant from a library, developed by somebody else for my own c++ projects. i have added two new classes called TriangleList and TriangleLists to the library as i wanted new class types for the project. once, i added the hpp and cpp files to the library, i got the massage like creating ../lib/libExtraction.a .
however, when i called back the functions, that i written in the new classes, from my own project, i got the error massages like
`[Linker error] undefined reference to `TriangleLists::Erase()`
(the above one for the Erase function)
then, when i removed the .cpp file and wrote everything in .hpp it works.
But, i would like to maintain two files for the hpp and cpp further. so, please tell me how to solve this link error problem as i want to learn this. thank you in advance.
First thing you need to check is if you're exporting the class:
class __declspec(dllexport) TriangleLists
{
//members
};
When you include the header in a different project however, you need to specify that the class is imported, so:
class __declspec(dllimport) TriangleLists
{
};
This is usually achieved with preprocessor directives:
#ifdef BUILDING_FIRST_PROJECT
#define DLLIMPEXP _declspec(dllexport)
#else
#define DLLIMPEXP _declspec(dllimport)
#endif
//TriangleLists.h
class DLLIMPEXP TriangleLists
{
}
and only define BUILDING_FIRST_PROJECT in your first project. That way, when building the first project, you'll be exporting the class, and when you include the header in another project, you're importing it.
Second thing is that the other project must link to the .lib file generated by the first project.
The reason it works when you move the implementation to the header is that the method becomes inline, so there's no lookup for it in the lib files, as it's definition is already known.
EDIT: Forgive my noobish-ness, I haven't ever implemented a wrapper .dll before! :S
I've been tinkering a bit with some of the recently released Kinect Sensor hacks (namely OpenKinect and OpenNI) and I'm now trying to wrap the functionality in a *.dll for use in various "test" programs that I hope to write.
So far I've set up a *.dll project and have got a lot of the library functionality in, however I'm getting C4251 compiler warnings all over the place.
In the project settings I've got the OpenNI.lib file statically linked, so far my library header looks like this:
#ifdef LIBKINECT_EXPORTS
#define LIBKINECT_API __declspec(dllexport)
#else
#define LIBKINECT_API __declspec(dllimport)
#endif
// This class is exported from the LibKinect.dll
class LIBKINECT_API CLibKinect
{
public:
CLibKinect(void);
~CLibKinect(void);
bool Init(void);
protected:
private:
xn::Context m_xContext;
xn::DepthGenerator m_xDepthGen;
};
And my stdafx.h file contains:
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <XnOpenNI.h>
#include <XnCodecIDs.h>
#include <XnCppWrapper.h>
Now I've attempted to create a windows console app to test the library and I get lots of error C2653: 'xn' : is not a class or namespace name errors. I was hoping that in the application I would only have to include and link to the wrapper *.dll not all of the OpenNI stuff as well, so as to hide the underlying implementation, is this incorrect?
Since you want to hide the fact you are using xn namespace in your implementation, you should not put that in the library header file. The simplest way to solve this problem is to use the pimpl idiom.