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
Related
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.
I'm trying to use a C++ class from a native .dll project in a C++/CLI .dll project. Visual Studio 2010, .NET Framework 3.5. So far this is what I have:
// This is a common macro:
#ifdef ISDLL
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif
NativeProject:
//INativeType.h:
class DLL INativeType {
public:
virtual void Foo() = 0;
};
//NativeType.h:
class DLL NativeType : public INativeType {
public:
virtual void Foo();
};
extern "C" DLL INativeType CreateNativeType();
//NativeType.cpp:
void NativeType::Foo() {}
extern "C" DLL INativeType* CreateNativeType() {
return new NativeType();
}
C++/CLI Project:
// Wrapper.h:
#include "INativeType.h"
ref class Wrapper {
INativeType* m_nativeType;
};
// Wrapper.cpp:
#include "Wrapper.h"
#include "NativeType.h"
// in some method:
m_nativeType = CreateNativeType();
This gives me the following linker error:
error LNK2028: unresolved token (...) "extern "C" class INativeType * __stdcall CreateNativeType(void)"" ... in Wrapper.obj
Also, although the functions are correctly exported in NativeProject.dll, as I verified it with DependencyWalker, the linker also gives this warning:
warning LNK4199: /DELAYLOAD:NativeProject.dll ignored; no imports found from NativeProject.dll
The C++/CLI project is configured to delay load NativeProject.dll and also includes NativeProject.lib in its linker options. At this point I don't know how to diagnose this linker error. What am I doing wrong?
Why don't you just let the C++/CLI project instantiate the class directly instead of with a factory method?
Besides that, it just looks like you are re-inventing COM (using objects through interfaces). I would just instantiate full-blown C++ classes or, if you really need it, use full-blown COM.
EDIT: Make sure the factory method's calling convention is the same in both the client and the DLL.
I am trying to protect some C++ code by exporting as a DLL (on Windows/VS 2010).
In the example below var is set in the superclass constructor, and the debugger shows it is definitely set to reference something.
Test is constructed in the code that consumes the DLL the Test class is contained within.
But when go is called from on an instance of test (invoked from the DLL, but the invoking method is called by the DLL consumer) var is a null pointer (it's value is 0).
This is a simplification as I am not allowed to share the actual code.
//Headers
class Base {
public:
__declspec(dllexport) Base();
private:
Foo* var;
};
class Test : Base {
public:
__declspec(dllexport) Test();
__declspec(dllexport) void go();
private:
};
//Body
Base::Base() {
var = new Foo();
}
Test::Test() : Base() {
}
void Test::go() {
var->do_something();
}
In the consuming code, the header is
class Base {
public:
__declspec(dllimport) Base();
};
class Test {
public:
__declspec(dllimport) Test();
__declspec(dllimport) void go();
};
The actual code is much more complex, but I would be grateful if anyone can tell me whether there are known restrictions on instance variables with dllexport, or if it is more likely that I'm calling a method on a null pointer for Test, or perhaps it is a dllexport and inheritance problem. This code worked before I split the consumer code and DLL code was in the same project, it has only broken since splitting it up, dllexporting/dllimporting functions I want to expose into a second set of headers used by the consumer.
When you pass a Test by value from one place to another in the "consuming code", you'll cause slicing to occur because the client code is unaware of the variable and calculates an incorrect size for the class Test.
To solve this problem, you should declare the variable in the client code as well, or alternatively you can provide a static factory function of some kind and only allow the client code to pass pointers to Tests around to avoid slicing.
If you remove the instance variable from the code supplied to the customer, only your own code knows the real size of your object and can create it. From the top of my head you have two ways to go about this:
Supply a createTest static function that creates an instance of your class (factory method). The nicest thing to do here is to provide a pure interface (no instance variable).
If you only want to hide a specific part of your class you can use the pimpl idiom (wikipedia article).
Is there any reason to not use:
#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif
class fooEXPORT exportClass
{
public:
void function( void );
Foo * var;
}
If you want to hide your class (or part of your class), you could use it as a private member:
#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif
class classToHide;
class fooEXPORT exportClass
{
public:
void function( void );
classToHide * var;
}
And in Cpp:
#include "exportClass.h"
#include "classToHide.h"
void exportClass::function( void )
{
var->function();
}
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.
I am trying to understand an open source project, where I came across the following class declaration:
class STATE_API AttributeSubject : public AttributeGroup, public Subject
{
public:
AttributeSubject(const char *);
virtual ~AttributeSubject();
virtual void SelectAll() = 0;
virtual const std::string TypeName() const;
virtual void Notify();
virtual AttributeSubject *CreateCompatible(const std::string &) const;
virtual AttributeSubject *NewInstance(bool copy) const { return 0; };
virtual bool VarChangeRequiresReset(void) { return false; };
};
What does STATE_API before the class name AttributeSubject signify? Is it some sort of macro?
It's probably a typedef to __declspec(dllimport) or __declspec(dllexport) and is used inside DLLs on windows platform to export classes.
Neil is right, it's a macro.
It usually looks like this:
#ifdef INDSIDE_DLL
#define STATE_API __declspec(dllexport)
#else
#define STATE_API __declsped(dllimport)
#endif
You define INSIDE_DLL only in your dll and export all the classes declared with STATE_API macro.
It's a macro. What it expands to depends on your platform - it is cannot be part of standard C++ (unless it expands to nothing).
Is this the source code of a DLL project ?
If so, then STATE_API must be a preprocessor macro, enabling you to use the header in which this class is declared in both the library project and the application using the library.
in the library project, STATE_API would be defined to __declspec(dllexport)
in the project using the library, STATE_API would be defined to __declspec(dllimport)
This is usually achieved with something like this :
#ifdef USRDLL
#define STATE_API __declspec(dllexport)
#else
#define STATE_API __declspec(dllimport)
#endif
USRDLL being defined in the project options of the DLL.
It is a macro:
As a user of the class it is not that important.
It is some platform specific macro that is being used to help (probably) the compiler perform some operation.
As the designer of the class then you are trying to do somthing platform specific to the class and you have already done the research on what it expands into and what that expansion means.