Compiler Warning C4251: Problem exporting a class in a *.dll - c++

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.

Related

How to use precompiled header with dynamic library and console application?

I have the problem with precompiled header. It looks somewhat like that
ftpch.h
#pragma once
#include <vector>
#include <iostream>
#include <string>
#include <Windows.h>
ftpch.cpp
#include "ftpch.h"
Then I have a header file and cpp in my dll library.
test.h
#pragma once
// DLL_EXPORT is a macro that changes for dll and console app like that:
// __declspec(dllexport) and __declspec(dllimport)
class DLL_EXPORT Test
{
std::string foo() {return "ara ara"};
}
And this code compiles fine when I compile my dynamic library project, but fails to compile when I include "test.h" in my console app project and try to compile it. The error I get is:
C2039: 'string' is not a member of 'std'
Your header files should always be self-sufficient. Include your libraries (in this case <string>) where you need them, everywhere you need them, and only where you need them.
If your header requires a certain library to function, include it in that file; don't reply on a different header to have included that library already, because if that different file changes, you're out of luck.
You've already got #include guards through #pragma once, so adding #include <string.h> to the header files that need it won't cause collision, and will also make them more maintainable and easy to interpret.

compiling a #include <cstdlib> in Xcode - error during compilation: file not found

I have added one framework in my project, where to get the callbacks of framework I need to implement c++ code,for which I have added c++ classes which are .mm from .cpp
as per suggestions given in this link
I also came across few posts of StackOverflow, where I found either I have to go for C++ or Objective C source type(as suggestion of few members).
I am looking to compile c++ code along with Objective C classes,but I am getting file not found error (compile time) for #include <cstdlib> and #include <string>
Please let me know any one worked around it.or faced same Issue.
Thanks In Advance!!!
I think problem is that your's .h-file, where you have added C++ includes is included in other .m-files, not just in .mm.
There is several ways to solve this problem:
Use C++ includes only in .mm files. (don't use them in .h)
Change all files, that import yours header to .mm
Include them in
#ifdef __cplusplus
#endif
block. Also use this block for methods where C++ classes mentioned.
For example:
#ifdef __cplusplus
#include <string>
using namespace std;
#endif
#interface SomeClass
#ifdef __cplusplus
- (void) setName:(const string&) name;
#endif
#end
Also there is way to avoid #ifdef #endif block by using extensions and categories:
declare C++'s instance variables only in extensions.
create categories with additional .h-file for methods and properties, that use C++'s types.

Compile dll in Qt with VS compiler to use it in Borland

I have a package of C functions and I need to create DLL library from it, that can be used in C++ program. I haven't done any library before, so I am total beginner in that. I am working in Qt Creator.
My first try was to create it according to the manual Creating shared libraries, so I added these two lines to my project file:
TEMPLATE = lib
DEFINES += MYLIB_LIBRARY
Then I created mylib.h file
#ifndef MYLIB_H
#define MYLIB_H
#include "mylib_global.h"
#include "functions1.h"
#include "functions2.h"
#include "functions3.h"
class MYLIBSHARED_EXPORT Mylib
{
public:
Mylib(){};
};
#endif // MYLIB_H
Finally I added mylib_global.h:
#ifndef MYLIB_GLOBAL_H
#define MYLIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYLIB_LIBRARY)
# define MYLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYLIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYLIB_GLOBAL_H
To make functions usable in C++ I used these lines for each function in library
#ifdef __cplusplus
extern "C"{
#endif
void foo();
#ifdef __cplusplus
}
#endif
When compiling with MSVC2012 everything seems ok and I got some .dll file. But then I sent library to someone, who wanted to use it in Borland C++. He told me that I have to compile it with some DEF file to tell to VS compiler right names and with __stdcall instead of __cdecl. But I have no idea how to do it in Qt. Any explanation and help would be really appreciated. Thanks
P.S. I looked at posts Using VS dll in old Borland and Import VS dll in C Builder, but they
did not help me to understand the problem.
If you want to export the foo function, you need to tell the linker somehow.
What you were suggested is to use a .def file, which is quite easy.
Just create a file like exports.def in your project directory, and write in it something like:
EXPORTS
foo
Then go to your library project settings -> Linker -> Input -> Module Definition File
and fill in your .def file name

Ideal way to include headers from a DLL?

I've been testing things with multiple project setups where a console application accesses functions from several DLLs.
I thought about how to include the DLLs' headers in the console application. My current implementation is as follows but it's being a headache to manage and even sometimes runs into errors:
Each DLL project has a folder called "Include"
The Console application project references the Include folder of each DLL project (as suggested by msdn guide to working with DLLs)
Each DLL project contains a single header that includes all the headers in that one project
The console application then #includes these "master headers"
Every project uses the pre-compiled header "stdafx" and each file #includes it.
It worked out fine until I started overloading operators.
I believe the grief is caused by the pre-compiled header somehow, here's and example of my current usage of stdafx:
#define DLL // Found in every DLL, not in the console project
#ifdef DLL
#define DLLEI __declspec(dllexport)
#else
#define DLLEI __declspec(dllimport)
#endif
#include <iostream>
#include <vector>
#include "Include\Engine.h"
using namespace std;
With this I sometimes get some irrelevant random compiler errors that I can hackfix by excluding the header from the "master header" and including the troublemaker separately in the console app.
Suggestions what could be done better?
__declspec(dllexport) and __declspec(dllimport) definitions should be placed in every public Dll include file, or at least in the main Dll public include file, which includes all other files. These definitions should not be in stdafx.h.
#define DLL // Found in every DLL, not in the console project
This is incorrect, every Dll must have unique preprocessor definition. In your case, of one Dll depends on another, it always compiles another Dll functions as __declspec(dllexport)
Ensure that every header has #pragma once in the beginning.
Consider using common Include directory for all projects.
As already mentioned in the comments, using namespace can be used only in source files.
This article answered quite a few of my questions.
http://www.codeproject.com/Articles/6351/Regular-DLL-Tutor-For-Beginners

When C++ DLL Program Exits: Run-Time Check Failure #2

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.