Polymorphic DLL exports - c++

I am currently working on a project that uses a DLL and an application that uses the DLL. The DLL is exported as an abstract base class header and a concrete implementation derived from the abstract base, as usual:
---- TaskInterface.h ----
class Task {
public:
virtual int func1(void) = 0;
virtual int func2(void) = 0;
};
extern "C" __declspec(dllexport) Task * APIENTRY newTask();
--- Task.h ---
class TaskImpl : public Task
{
public:
virtual int func1(void);
virtual int func2(void):
};
Task * APIENTRY newTask()
{
return static_cast<Task*>( new TaskImpl );
}
--- Task.cpp ---
int TaskImpl::func1(void)
{
// ...
}
int TaskImpl::func2(void)
{
// ...
}
This works so far as intended, the application includes "AbstractTask.h" and then calls the respective function defined by class TaskImpl:
--- TheApplication.cpp ---
Task aTask = newTask();
aTask->func1();
aTask->func2();
// ...
However, now the Application discovers that what the default implementation in class TaskImpl does is not enough and therfore defines within its own scope a new derived class, like so:
--- AppImpl.h ---
#include "TaskInterface.h"
class AppImpl : public Task
{
int func1(void) = { /* new stuff */ }
int func2(void) = { /* new stuff */ }
};
and then defines in TheApplication.cpp:
--- TheApplication.cpp ---
#include "AppImpl.h"
ApplImp * aNewTask = static_cast<Task*>(newTask());
aNewTask->func1();
aNewTask->func2();
In what context do you think func1() and func2() are called? Correct: It's still the concrete implementation inside the DLL class TaskImpl and not the derivates defined by class AppImpl.
And basically this is my problem: I want to use a default implementation from inside a DLL, but I want to be able to expand it on the Application side, so unless I have explicitly overriden a function in ApplImp.h, I fall back to the one defined in TaskImpl inside the DLL.
Is this possible? If so, what am I doing wrong? If not, how could I accomplish something equivalent?
I already toyed with exporting both "TaskInterface.h" and "Task.h" and then have ApplImp.h include the concrete class in the DLL, but the compile doesn't like that for obvious reasons => can't export newTask() twice.
Any help is appreciated!

As you need to allocate and deallocate via the DLL anyway, I'd suggest providing a wrapper class alongside the DLL. This wrapper class then could be designed to be inherited from.
class Task {
public:
virtual int func1(void) = 0;
virtual int func2(void) = 0;
};
// v~~~~v probably dllimport in the header you ship
extern "C" __declspec(dllexport) Task * APIENTRY newTask();
class TaskWrapper {
public:
TaskWrapper() : m_ptr( newTask() ) {}
virtual ~TaskWrapper() { deleteTask(m_ptr); }
virtual int func1(void) { m_ptr->func1(); }
virtual int func2(void) { m_ptr->func2(); }
protected: // implementation omitted for brevity
TaskWrapper(TaskWrapper const&);
TaskWrapper(TaskWrapper&&);
TaskWrapper& operator= (TaskWrapper const&);
TaskWrapper& operator= (TaskWrapper&&);
private:
Task* m_ptr; // preferably a unique_ptr
};
You could also let TaskWrapper derive from Task.

If I understand the question correctly, you want ApplImp to derive from TaskImp, and call into TaskImpl member implementations as needed, using standard C++ syntax..
You can't do that directly because the application and DLL are linked separately and have no compile-time knowledge of each other. The application doesn't know about TaskImpl at compile time, thus the compiler cannot derive from it and cannot create a Vtable that may be a combination of funcitons from application and DLL.
You chould compose the objects, i.e. create an instance of TaskImp inside ApplImp and delegate all functions to the TaskImp instance inside of ApplImp. That's inconvenient in many cases.
A more convenient way is to export the implementation of TaskImpl from the DLL: declare the whole class as __dllexport. Unfortunately, that's the least portable way to do it and in a large project, it may lead to a huge dll export section with 10000 C++-name-mangled entries. But you might be able to use TaskImpl as a base class in other DLLs or the application.
Btw, this won't compile because ApplImp is derived from Task, and Task* cannot be cast implicitly to ApplImpl.
ApplImp * aNewTask = static_cast(newTask());

Related

C++ nullptr member objects cause "Unable To Read Memory" in DLL Shared Library

I'm crating a DLL in C++ which handles different classes: in particular I have a main class which have a lot of member objects of the other the classes. For exmaple I have my class "A" which has a member of class "B":
Class A header
#include "BClass.h"
class __declspec(dllexport) A
{
B* objectB = nullptr;
public:
A();
initClassB();
}
Class A cpp:
A::A() { // Class A constructor. In these statements B is still nullptr}
A::initCLassB() { objectB = new B() }
Class B header:
class __declspec(dllexport) B
{
int x;
bool y;
char* z;
public:
B() { // class B constructor}
}
When I import my DLL in my target project, it compiles with no error, and until here everything's ok.
My main is something like:
#include "AClass.h"
int main()
{
A a;
return 0;
}
Notice that I don't invoke initClassB() in my main and this cause the error "Unable To Read Memory". If I explore the debugger I see that the error is related to all A::objectB members.
Why is this happening? Can't the shared library handle a nullptr member object?
I'm quite new in compiling DLL and this error looks a bit weird to me
DLLs on windows need to export their symbols when building the dll. Client code that uses the library needs to import it.
In your header for class B:
class __declspec(dllexport) B
This is what you want when building the library, but in code that uses it, you want it to be dllimport instead. Usually people use macros to toggle this, with it defaulting to import, and only exporting if a special commandline macro is set.
See this Macro for dllexport/dllimport switch

How can I change what a class inherits from at compile-time?

In my quest to create a cross-platform GUI Framework, I have hit the following snag:
Suppose I have a central "Window" class, in the project's general, platform-independent include folder:
//include/window.hpp
class Window
{
//Public interface
}
I then have several platform-dependent implementation classes, like so:
//src/{platform}/window.hpp
class WinWindow {...}; //Windows
class OSXWindow {...}; //OSX
class X11Window {...}; //Unix
Finally, there is the original Window class' .cpp file, where I want to "bind" the implementation class to the general class. Purely conceptually, this is what I want to be able to do:
//src/window.cpp
//Suppose we're on Windows
#include "include/window.hpp"
#include "src/win/window.hpp"
class Window : private WinWindow; //Redefine Window's inheritance
I know this is by no means valid C++, and that's the point. I have thought of two possible ways to solve this problem, and I have problems with both.
pImpl-style implementation
Make Window hold a void pointer to an implementing class, and assign that to a different window class for each platform. However, I would have to up-cast the pointer every time I want to perform a platform dependent-operation, not to mention include the platform dependent file everywhere.
Preprocessor directives
class Window :
#ifdef WIN32
private WinWindow
#else ifdef X11
private X11Window //etc.
This, however, sounds more like a hack than an actual solution to the problem.
What to do? Should I change my design completely? Do any of my possible solutions hold a little bit of water?
Using typedef to hide the preprocessor
You could simply typedef the appropriate window type instead:
#ifdef WINDOWS
typedef WinWindow WindowType;
#elif defined // etc
Then your window class could be:
class Window : private WindowType {
};
This isn't a very robust solution, though. It is better to think in a more Object Oriented way, but OO programming in C++ comes at a runtime cost, unless you use the
Curiously repeating template pattern
You could use the curiously repeating template pattern:
template<class WindowType>
class WindowBase {
public:
void doSomething() {
static_cast<WindowType *>(this)->doSomethingElse();
}
};
Then you could do
class WinWindow : public WindowBase<WinWindow> {
public:
void doSomethingElse() {
// code
}
};
And to use it (assuming C++ 14 support):
auto createWindow() {
#ifdef WINDOWS
return WinWindow{};
#elif UNIX
return X11Window{};
#endif
}
With C++ 11 only:
auto createWindow()
->
#ifdef WINDOWS
WinWindow
#elif defined UNIX
X11Window
#endif
{
#ifdef WINDOWS
return WinWindow{};
#elif defined UNIX
return X11Window{};
#endif
}
I recommend using auto when you use it, or using it in combination with a typedef:
auto window = createWindow();
window.doSomething();
Object Oriented Style
You could make your Window class be an abstract class:
class Window {
protected:
void doSomething();
public:
virtual void doSomethingElse() = 0;
};
Then define your platform-dependent classes as subclasses of Window. Then all you'd have to do is have the preprocessor directives in one place:
std::unique_ptr<Window> createWindow() {
#ifdef WINDOWS
return new WinWindow;
#elif defined OSX
return new OSXWindow;
// etc
}
Unfortunately, this incurs a runtime cost through calls to the virtual function. The CRTP version resolves calls to the "virtual function" at compile time instead of at runtime.
Additionally, this requires the Window to be declared on the heap whereas CRTP doesn't; this might be a problem depending on the use case, but in general, it doesn't matter that much.
Ultimately, you do have to use the #ifdef somewhere, so you can determine the platform (or you could use a library that determines the platform, but it probably uses #ifdef too), the question is just where to hide it.
You can use the CRTP pattern to implement static polymorphism:
class WindowBase {
virtual void doSomething() = 0;
};
template<class WindowType>
class Window : public WindowBase {
// Static cast when accessing the actual implementation:
void doSomething() {
static_cast<WindowType*>(this)->doSomethingElse();
}
};
class X11WindowImpl : public Window<X11WindowImpl> {
void doSomethingElse() {
// blah ...
}
};
class Win32WindowImpl : public Window<Win32WindowImpl> {
void doSomethingElse() {
// blah ...
}
};
Since your code will be compiled to satisfy a particular target, this should be the leanest option.
It's okey. You could also write one class and define it's content using #ifdef etc., but your solution isn't a hack. Just a proper way to write multiplatform code if you have no other choice.

QLibrary - import a class

I have a QT library and I want to import it in another project.
Now, since I want that, even when I modify the library, the other project does not need to be compiled again, I started using QLibrary.
But... I can't import a class. Or better, I can import the class, but I can't access its methods.
This is the example I made.
This is the class declaration:
class TESTDLL_LIBSHARED_EXPORT TestDLL_lib
{
public:
TestDLL_lib();
int a;
int b;
int c;
int getValues();
};
and this the implementation:
#include "testdll_lib.h"
TestDLL_lib::TestDLL_lib()
{
a = 10;
b = 20;
c = 30;
}
int TestDLL_lib::getValues()
{
return a+b+c;
}
extern "C" TESTDLL_LIBSHARED_EXPORT TestDLL_lib* create_TestDLL_lib()
{
return new TestDLL_lib();
}
while this is the main file, in the other project:
#include <testdll_lib.h>
#include <QDebug>
#include <QLibrary>
int main(int argc, char *argv[])
{
QLibrary library("TestDLL_lib");
if (library.load())
{
typedef TestDLL_lib* (*create_TestDLL_lib_fun)();
create_TestDLL_lib_fun create_TestDLL_lib = (create_TestDLL_lib_fun)library.resolve("create_TestDLL_lib");
if (create_TestDLL_lib)
{
TestDLL_lib *myClassInstance = create_TestDLL_lib();
if (myClassInstance)
{
//qDebug() << QString::number(myClassInstance->getValues());
qDebug() << QString::number(myClassInstance->a) + " " + QString::number(myClassInstance->b) + " " + QString::number(myClassInstance->c);
}
}
library.unload();
}
}
Now, I can access all the data values (a, b, c) of the object myClassInstance (and, if i change them in the DLL, they also get changed in the program without a rebuild) but I can't call myClassInstance->getValues() because I get
main.obj:-1: error: LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall TestDLL_lib::getValues(void)" (__imp_?getValues#TestDLL_lib##QAEHXZ)
How can I solve this? Is it possible to call methods from imported classes?
Thank you..
You cannot call methods on classes imported at runtime. This is because the compiler links these calls at compile-time and not at run-time (which it cannot do). A way out is provided by our good ol' friend, the vtable:
You can, call virtual methods on classes implementing an interface (the interface is not "imported" at runtime). That means to define a class defining the interface using virtual (possibly pure virtual) methods. TestDLL_lib would then inherit that interface, implementing the methods. You would refer to the TestDLL_lib instance via that interface and call methods trough that interface, effectively calling them trough the vtable of the interface, which is "superseded" by TestDLL_libs vtable.
Don't forget to make your d'tor virtual and to add a virtual dtor to the interface. If you don't do that you cannot safely delete instance trough the interface pointer.
I might also explain why you can access members, but not call functions on "imported" classes. The members are accessed by memory location, and the memory location is solely defined by the compiler. Thus the compiler generates the code to access members without ever referring to any of the classes' symbols (methods and so on). This in turns leads to no linkage dependency. Note however that you would need to recompile both the DLL and the application using the DLL if you change the class, e.g. adding or removing a member, since that changes the memory layout.
class TestInterface
{
public:
virtual ~TestInterface()
{
}
virtual int getValues() = 0;
}
class TESTDLL_LIBSHARED_EXPORT TestDLL_lib : public TestInterface
{
public:
TestDLL_lib();
virtual ~TestDLL_lib();
int a;
int b;
int c;
int getValues() override; // MSVC may not support "override"
};
// return pointer to interface!
// TestDLL_lib can and should be completely hidden from the application
extern "C" TESTDLL_LIBSHARED_EXPORT TestInterface *create_TestDLL_lib()
{
return new TestDLL_lib();
}

Implementing an interface in dll which is declared in main app - C++

I have a main app which has an interface(abstract class) and this interface need to have implementations both in main app and an external dll.
I will be using the pointer to this interface to access the methods, so i will be assigning pointer to address of the any one of the implementations based on some condition.
How can this be achieved?
I came across a question in stack overflow where the answer marked as solution says
An interface in main app
class IModule
{
public:
virtual ~IModule(); // <= important!
virtual void doStuff() = 0;
};
can be implemented in main app
class ActualModule: public IModule
{
/* implementation */
};
And can export a function from dll to return pointer to implementation in dll
__declspec (dllexport) IModule* CreateModule()
{
// call the constructor of the actual implementation
IModule * module = new ActualModule();
// return the created function
return module;
}
How will dll come to know that something like IModule exists?
Can i mark the IModule as extern and use in dll?
'How will dll come to know that something like IModule exists?'
Because the dll code will include the header file where IModule is declared. Header files are the way to share declarations between different source files. Dlls make no difference to this, and there is no need to mark IModule as extern.
BTW I would do this
virtual ~IModule() {} // <= important!

Interfaces, hiding concrete implementation details in C++

I have a question regarding hidinging interface details in C++ libraries. The problem is ilustrated with the following example:
Let's say w have a class called ISystem which exposes methods like Init, Run, Tick, Shutdown, GetXXXSubSystem.
Where X are pointers various interfaces like: ISoundSystem, IInputSystem
We also have concrete implementations of ISystem like:
Win32System, OSXSystem etc.
These specific implementations use a pimpl idiom to hide internals
and for example Win32System instantiates Win32RawInputSystem
as input system manager.
All such managers do have their own Init, Run, Tick and Shutdown methods
which are not part of the interface (only concrete implementation) and these are run and managed by the concrete system implementation.
The user calling GetXXXSubSystem gets interface pointer without those methods (Init etc..) but
still he could cast the pointer he gets to concrete implementation
and trigger methods like Init Run Tick etc. which he shouldn't have access to.
The question is, is it possible to hide the concrete class somehow? I tried to make those methods
protected in the concrete implementations and template the class on type which would eventually be friend but this appears to be prohobited and existing hacks do not work with VC11.
The only way I can think of right know is to transfer the concrete implementation declaration from header
into the cpp file of Win32System class but I see ahuge drawback of doing this (even not sure if this would work), because this way each subsystem
would have to be also part of this cpp file and it would become a maintainability nightmare.
Another solution I am thinking about is using factory method like
(RawInput.h)
IInputSystem* CreateRawInputSystem();
(RawInput.cpp)
class RawInput : public IInputSystem {}; ...
and move definition of the class to cpp file but then, how I would acces this type from other parts of my library (ie in Win32System impl)?
Is it possible to include .cpp files form other .cpp files?
Thanks in advance for any tips.
If you're developing a library here, then you can simply choose not to export the header files of the concrete classes that you do not want to expose. You cannot cast to a class of which you do not have a definition.
Example :
MyProjectFolder/Src/Export/ISystem.h
#ifndef ISYSTEM_H
#define ISYSTEM_H
#include "IInputSystem.h"
class ISystem
{
public:
virtual ~ISystem() {};
virtual void Run()=0;
virtual IInputSystem* GetInputSystem()=0;
};
#endif
MyProjectFolder/Src/Export/IInputSystem.h
#ifndef IINPUTSYSTEM_H
#define IINPUTSYSTEM_H
class IInputSystem
{
public:
virtual ~IInputSystem() {};
virtual void Foo()=0;
virtual void Bar()=0;
};
#endif
MyProjectFolder/Src/Export/Win32System.h
#ifndef WIN32SYSTEM_H
#define WIN32SYSTEM_H
#include "ISystem.h"
class Win32System : public ISystem
{
public:
Win32System();
virtual void Run();
virtual IInputSystem* GetInputSystem();
private:
struct impl;
impl* m_pImpl;
};
#endif
MyProjectFolder/Src/Win32RawInputSystem.h
#ifndef WIN32RAWINPUTSYSTEM_H
#define WIN32RAWINPUTSYSTEM_H
#include "IInputSystem.h"
class Win32RawInputSystem : public IInputSystem
{
public:
virtual void Foo();
virtual void Bar();
virtual void Run(); // you do not want to expose that function
};
#endif
MyProjectFolder/Src/Win32System.cpp
#include "Win32System.h"
#include "Win32RawInputSystem.h"
struct Win32System::impl
{
Win32RawInputSystem inputSys;
};
Win32System::Win32System()
: m_pImpl(new impl)
{
}
void Win32System::Run()
{ // run run run
}
IInputSystem* Win32System::GetInputSystem()
{
return &m_pImpl->inputSys;
}
So when building your project its include search path is not only Src/ but also Src/Export/. From within your library project you can use all classes, including Win32RawInputSystem. When deploying your library you only give away those headers that reside in the Src/Export/ folder. Clients can still use the library, but they can never cast IInputSystem* to Win32RawInputSystem* because they do not have that header. Therefore the users of that library can invoke Foo() and Bar() on the IInputSystem*, but they'll never be able to invoke Run().