Static data in DLL - c++

My problem is remarkably similar to this one: A class in a DLL has a static member. In this case, the static member is of Type QString (a QT type) and provides a name for the class. I provide the normal export on class level: __declspec(dllexport).
When I link the DLL with my class to another project and try to compile it, I get an "unresolved external symbol" error for the static data. I verified two things:
Dumpbin definitely reports the static data member to be exported by compiled DLL.
Actually, the static data member seems not to be used in the application which reports the error.
HEADER file (.h) in DLL is:
class __declspec(dllexport) MyClass {
public:
virtual ~MyClass();
static const QString JUST_A_NAME;
};
IMPLEMENTATION file (.cpp) in DLL is:
#include "MyClass.h"
MyClass::~MyClass() { }
const QString MyClass::JUST_A_NAME("call_me_al");
In contrast to already mentioned post, I avoided methods to be inline, e.g. implementation is obviously not in the header. The type, QString (see line 83 ff.), contains several inlines itself. May that cause the error?
EDIT: I added an import statement in the header of my application. It is located before any includes.
HEADER file (.h) in APPLICATION is:
class __declspec(dllimport) MyClass {
public:
virtual ~MyClass();
static const QString JUST_A_NAME;
};
The error remains the same:
error LNK2001: non resolved external symbol ""public: static class QString const MyClass::JUST_A_NAME" (?JUST_A_NAME#MyClass##2VQString##B)". <name of .obj file from application>

In your application header file you need to do two things.
When exporting, declare the definition __declspec(dllexport)
When importing, declare the definition __declspec(dllimport)
You obviously cannot do them both at the same time.
What you have to do is define a macro like this:
#ifdef __COMPILING_MYLIB
#define MYLIBAPI __declspec(dllimport)
#else
#define MYLIBAPI __declspec(dllexport)
#endif
Then declare your exports like this:
// mylib.h
class MYLIBAPI MyClass {
public:
virtual ~MyClass();
static const QString JUST_A_NAME;
};
Then, when compiling MYLIB, you pass -D__COMPLING_MYLIB to the compiler, which triggers the #if above.
That way, when compiling the library itself, the header file declares things as exports, but when compiling things which will use the library, they are declared as imports.

Related

Dll export symbol of function from static linked library

I am wrapping a static library in Dll to hide a lot of the implementation stuff since only 4-5 functions are needed and to avoid providing all third-party libraries and many header files. I seem to be having an issue with exporting a function to the dll from the static lib.
The static lib has settings classes / structs similar to the one below
struct FooSettings
{
bool Read(const std::string& file); // implemented in .cpp
bool Write(const std::string& file); // implemented in .cpp
// rest members, just plain types
};
In the Dll side
#include "FooSettings.h"
#if defined(WIN32) || defined(_WIN32)
#if defined(LIB_EXPORT)
// DLL Build, exporting symbols
#define LIB_API __declspec(dllexport)
#elif LIB_IMPORT
// DLL use, importing symbols
#define LIB_API __declspec(dllimport)
#endif
#endif
#ifndef LIB_API
#define LIB_API
#endif
class LIB_API LibSDK
{
public:
LibSDK();
~LibSDK();
FooSettings get() const noexcept;
void set(const FooSettings& settings) const noexcept;
void dummy()
{
foo.Read("");
}
private:
// etc...
};
I can call dummy() on the "client" side without any issues
but the code below leads to unresolved symbols
FooSettings foo;
foo.Read("");
I would have expected that the FooSettings:Read is at least exported since it is part of a dummy function. Am I missing something ? My preference is to export it without the dummy function but I dont seem to be able to make it work either way.
Coming back to all this, the answer was actually to #define LIB_EXPORT in the static library build as well which I did not expect.
I did not think that such a thing would be needed for a static .lib files since all they are is just a bundle of object files so they did not need to be marked for export. Apparently, it was needed if you want to export the functions from the static lib to your wrapper dll.

Defining a struct imported from DLL works only when its constructor is defined in the header file [duplicate]

This question already has answers here:
How do I safely pass objects, especially STL objects, to and from a DLL?
(4 answers)
Closed 7 years ago.
I have a class which has two overloaded functions. How do I export it from a dll and also how to use it by other C++ classes? My class looks like this:
#define DECLDIREXP __declspec(dllexport)
#define DECLDIRIMP __declspec(dllimport)
class DECLDIREXP xyz
{
public:
void printing();
void printing(int a);
};
using namespace std;
void xyz::printing()
{
cout<<"hello i donot take any argument";
}
void xyz::printing(int a)
{
cout<<"hello i take "<< a <<"as argument";
}
A common approach is to have a single macro (let's call it EXPORT) which either expands to dllimport or dllexport depending on whether some sort of "building the DLL right now" define is set, like this:
#ifdef MAKEDLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif
class EXPORT xyz {
// ...
};
The idea is that when building your DLL, you add MAKEDLL to the preprocessor definitions. That way, all the code will be exported. Clients who link against your DLL (and hence include this header file) don't need to do anything at all. By not defining MAKEDLL, they will automatically import all the code.
The advantage of this approach is that the burden of getting the macros right is moved from the many (the clients) to just the author of the DLL.
The disadvantage of this is that when using the code above as it is, it's no longer possible to just compile the code directly into some client module since it's not possible to define the EXPORT macro to nothing. To achieve that, you'd need to have another check which, if true, defines EXPORT to nothing.
On a slightly different topic: in many cases, it's not possible (or desired!) to export a complete class like that. Instead, you may want to just export the symbols you need. For instance, in your case, you may want to just export the two public methods. That way, all the private/protected members won't be exported:
class xyz
{
public:
EXPORT void printing();
EXPORT void printing(int a);
};
As I remember, normally, you export not a class but a factory function that creates a new instance of class and returns a pointer. The class declaration resides in header file for compile time.
I may be wrong about the example (that was long ago), but here how it should approximately look like:
Header file (.h):
class MyClass { ... };
extern "C" DLL_API MyClass* createMyClass();
Source file (.cpp):
DLL_API MyClass* createMyClass() {
return new MyClass();
}
Define MY_DLL_EXPORT while compiling, see foraidt's answer example.
One another option:
Use the default defined macro local to the project.
You can see the default defined macros local to the project in the below location:
Properties -> C/C++ -> Preprocessor -> Preprocessor Definition.
Example:
Suppose your Project Name is: MyDLL
Default Macro Local to that project: MYDLL_EXPORTS
#ifdef MYDLL_EXPORTS
/*Enabled as "export" while compiling the dll project*/
#define DLLEXPORT __declspec(dllexport)
#else
/*Enabled as "import" in the Client side for using already created dll file*/
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT Class_Name {
//....
}
When compiling your library you should define a macro (command line preprocessor definition), let's call it MY_DLL_EXPORT.
Then in your library's code do something like this:
#ifdef MY_DLL_EXPORT
# define DLL_API __declspec(dllexport)
#else
# define DLL_API __declspec(dllimport)
#endif
class DLL_API some_class { /*...*/ }

Creating Qt plugin and using non-virtual functions

First of all I use VS 2008 and dynamic build of Qt 4.7.0.
interface.h:
class PluginInterface
{
public:
virtual void foo() = 0;
};
Q_DECLARE_INTERFACE(PluginInterface, MY_PLUGIN_VERSION)
And I have and class which implements this interface:
myplugin.h
class MyPlugin: public QObject, public PluginInterface
{
public:
Q_OBJECT
Q_INTERFACES(PluginInterface)
virtual void foo(); // this functions is implemented in cpp file.
static QString goo(); // this function is also implemented in cpp file.
};
So when I use this plugin in other project(MySpecialPlugin) which will be compiled as dynamic-link library(actually also a plugin interface implementation) I can't call
MyPlugin::goo();
The header of "MyPlugin.h" is visible for MySpecialPlugin. And Ms VS2008 successfully compile the project. But I have error on link step LNK2001, undefined reference. But when change static void goo(); to virtual void goo(); it works.
I'm using Q_EXPORT_PLUGIN2 macro for creating plugins.
What I'm doing wrong? Does Qt set additional requirements on implementation of plugin interfaces?
First of all you need to export your class (on windows it's magic like __declspec(dllexport) after class keyword when compiling your "myplugin" and __declspec(dllimport) when compiling code using it (in this case MySpecialPlugin). You can achieve it with simple define. read more
#ifdef _WIN32
#ifdef MYPLUGIN_COMPILE
#define MYPLUGIN_EXPORT __declspec(dllexport)
#else
#define MYPLUGIN_EXPORT __declspec(dllimport)
#endif
#else
#define MYPLUGIN_EXPORT
#endif
class MYPLUGIN_EXPORT MyPlugin
{
// implementation
};
And add MYPLUGIN_COMPILE to preprocessor section of MyPlugin
You need to link against exporting library
Calling static and "normal" methods differs from calling virtual methods... static and "normal" methods are always at certain address and your code needs to know where is it... virtual call "checks" class vtable at what address your method has implementation and get that address "dynamicly" from that table. Additionaly win32 VC platform requires to define that something is "exported" (exposed) to access from outside of dll. So basicly if you want to call anything from MyPlugin directly (every member that is not virtual is called directly), you have to export it on win32 VC platform. Note that calling directly virtual method with MyPlugin::foo() will cause same error

C++ symbol export for class extending template class

I'm working on a C++ project built with Visual Studio 2008.
I'm defining (in a project producing a dll) a template class and a derived, not-template, one:
template <class T>
struct DLL_EXPORT Base {
int base() { return 1; }
};
struct DLL_EXPORT Deriv: public Base<Deriv> {
int deriv() { return 1; }
};
the DLL_EXPORT is the usual stuff:
#ifdef COMPILING_MY_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
Now, when I'm trying to use my Deriv class in another project, the trouble is starting. If I use only the function from Deriv, it works well:
Deriv d;
d.deriv();
But if I try to call d.base(), I get the following linker error:
error LNK2019: unresolved external symbol "__declspec(dllimport) public: int __thiscall Base<struct Deriv>::base(void)" (__imp_?base#?$Base#UDeriv####QAEHXZ)
If, elsewhere in my dll code, I'm using the d.base() function, it works well, and the linker error disappear in the "user" project. And if I remove the template part (it's not really useful in my example, but in the real-life situation it is), everything is fine.
It looks like the function don't get compiled if it's not used, or something equivalent. Any idea ?
Thanks in advance.
don't use __declspec(dllexport) on template definitions since they are not exported (they are not real code until instantiated).
They are only in the header file for usage by sources. You can use __declspec(dllexport) on specializations of templates ,but you must instatiated those at least once in your DLL.
If that is your problem, you might be able to fix it by explicitly instantiating the template.
In one of the .cc files in your DLL (not header file), include your template definition and write:
template int Base<Deriv>::base();
This should force the compiler to put the code for Base<Deriv>::base() into that compilation unit so your linker can find it.
I don't know much about this, but I think you might be able to fix it by writing
template struct Base<Derive>;
somewhere in your source file. (or perhaps template DLL_EXPORT struct Base<Derive>;)

Unreferenced external symbol during DLL function call

I'm having problems in implementing a class in a DLL in the same way it is explained here
. I have my interface with all the methods declared as virtual, I have my class that implements the interface and I have the method that should create the object of the class. The problem is here, when I try to use it I get a "unreferenced external symbol" error. Why?
class IXYZ
{
virtual void XXX() = 0;
};
class XYZ : public IXYZ
{
void XXX();
}
#ifdef __cplusplus
extern "C" __declspec(dllexport) IXYZ* __stdcall GetIXYZ();
#endif
and I use it inside my win32 program with:
IXYZ *myvar = GetIXYZ();
In my exe program I've included the .h file of the dll
If you've correctly defined the function in the DLL, and it is exported properly, then the only plausible explanation is that there is something wrong with your use of the .lib file in the application that uses the DLL.