I know about the Strategy and Abstract Factory design patterns - however they don't solve my current problem:
I'm creating a C++ library that offers a very basic GUI. However I want the user to be able to choose at compile time which GUI library to use (say Qt or FLTK) to actually render the GUI. The user should however only need to know about the methods in my library.
It should be possible to compile the same code without any changes using either a Qt backend or an FLTK backend.
I thought of something like:
class A
{
// do things that are not specific to QT or FLTK here as there are many
// methods I will need independent of the backend
}
class QT_A : public A
{
// Implement the actual creation of a window, display of a widget here using Qt
}
class FLTK_A : public A
{
// Implement the actual creation of a window, display of a widget here using FLTK
}
The problem is that I do not want the user to know about QT_A or FLTK_A. The user (developer) should just deal with A. Also, I can't have both variants at the same time as I don't want my library to depend on both Qt and FLTK; just whichever was chosen at compile time.
One option is the Pimpl idiom described in another answer.
Another option is a factory returning a pointer to the interface class:
std::unique_ptr<A> make_A()
{
#if defined(USING_QT)
return std::unique_ptr<A>(new QT_A(...));
#elif defined(USING_FLTK)
return std::unique_ptr<A>(new FLTK_A(...));
#else
#error "No GUI library chosen"
#endif
}
The Pimpl idiom may be an alternative. It allows you to create a common interface without framework dependent members.
class A
{
struct impl;
std::unique_ptr<impl> pimpl; // or scoped_ptr/auto_ptr on non-C++11
public:
A();
~A();
void do_sth();
};
Then, the source file can provide different implementations of impl depending on the backend.
#ifdef QT
struct A::impl : QWidget { // Make it polymorphic, if you need
QImage img;
QString data;
};
void A::do_sth()
{
impl->make_it(); // full access to the Qt things
}
A::A()
: pimpl(new ...)
{
}
A::~A() {} // no need for delete thanks the smart pointer
#endif
No need of fancy patterns.
You distribute
headers of A;
a library that contains A, QT_A, and make_A function;
another library that contains A, FLTK_A and another implementation of make_A function.
The user links to either library.
Related
Recently, I'm working on something like reflection in c++ using by my plugin system. Right now, I wonder if I can convert a super-class pointer into sub-class pointer given the string name of sub-class:
class SuperClass
{
public:
SuperClass(const string &name):class_name(name){}
// a convert function like
// return value should variant like SubClassA * or SubClassB *
// SubClassA * ConvertByName();
private:
string class_name;
};
class SubClassA: public SuperClass
{
public:
SubClassA():SuperClass("SubClassA")
};
class SubClassB: public SuperClass
{
public:
SubClassB():SuperClass("SubClassB")
}
when using:
// some place create instance
SuperClass *one = new SubClassAï¼›
SuperClass *two = new SubClassB;
// other place using
auto a = one->ConvertByName(); // a is of type SubClassA
auto b = two->ConvertByName(); // b is of type SubClassB
Can it be realized? Or is there any better way in c++?
[Update 1]
There my be some other sub-classes, such as, SubClassC, SubClassD, ...
So basically, we don't know what and how many sub-classes are derived from this SuperClass. What we know about sub-class is only its class name in string format.
[Update 2]
My motivation
I need this for plugin system. I want to create a plugin anytime, but don't want hack into my plugin core system codes. That is plugin codes are isolated from projects. A plugin system will never know what and how many plugins are added into system until runtime
Possible, well, this way you manually somewhat reimplement dynamic dispatch and make your class a kind of sealed.
struct Base {
Base(std::string type_id): type_id(std::move(type_id)) {}
template<class F> auto visitThis(F &&f) const;
template<class F> auto visitThis(F &&f);
private:
std::string type_id;
};
struct Child1: Base { Child1(): Base("Child1") {}};
struct Child2: Base { Child2(): Base("Child2") {}};
template<class F> auto Base::visitThis(F &&f) const {
if(type_id == "Child1") {
return std::invoke(std::forward<F>(f),
static_cast<Child1 const *>(this));
}
else if(type_id == "Child2") {
return std::invoke(std::forward<F>(f),
static_cast<Child2 const *>(this));
}
else throw std::runtime_error("Unsupported subclass");
}
template<class F> auto Base::visitThis(F &&f) {
if(type_id == "Child1") {
return std::invoke(std::forward<F>(f), static_cast<Child1 *>(this));
}
else if(type_id == "Child2") {
return std::invoke(std::forward<F>(f), static_cast<Child2 *>(this));
}
else throw std::runtime_error("Unsupported subclass");
}
int main() {
std::unique_ptr<Base> b1 = std::make_unique<Child1>();
b1->visitThis([](Child1 const *ch) { std::cout << "Hi, Ch1!\n"; });
}
If your classes all have some virtual thing, consider using dynamic_cast
See this C++ reference for details, and read a good C++ programming book.
Read also the documentation of your C++ compiler (e.g. GCC)
Right now, I wonder if I can convert a super-class pointer into sub-class pointer given the string name of sub-class
This is not possible without specific coding and programming conventions
(since the class names do not exist at runtime). Look inside Qt or RefPerSys as an example.
A possible approach could be to write your C++ code generator to help you (so generate parts of your C++ code - probably some header file containing your class declarations-, like Qt does with its moc, and configure your build automation tool, e.g. your Makefile). Look perhaps inside ANTLR, SWIG, GPP, etc...
A more ambitious approach, if you use GCC, would be to write your own GCC plugin. Consider also extending Clang. This is worthwhile only for large existing code bases.
A plugin system will never know what and how many plugins are added into system until runtime
It seems that you are designing some plugin machinery. Take inspiration from Qt plugins or FLTK plugins. If on Linux, see manydl.c and consider generating some of the C++ code of your plugins (see e.g. this draft report, and the CHARIOT and DECODER European projects).
BTW, do you want to unload plugins (on Linux, call dlclose(3); read also then the C++ dlopen minihowto)? Do you have a multi-threaded application? If you do, you'll better have some locking (e.g. std::mutex) to avoid parallel plugin loading.
You could also consider generating at runtime some glue code: e.g. using libgccjit or asmjit, or simply generating some temporary C++ code (e.g. on Linux in /tmp/generated.cc that you would compile - maybe with popen(3) - using g++ -Wall -O -fPIC /tmp/generated.cc -o /tmp/generated-plugin.so) and later dlopen(3) that /tmp/generated-plugin.so. Read Drepper's paper how to write shared libraries (for Linux).
C++ does not ship enough information in binaries to write new code.
Dynamically linked C++ code do not carry enough information for other dynamically linked code to build a copy of the class at link time.
So there is no way, short of shipping a C++ compiler, to do exactly what you are asking. I have heard of some people who go that far, and embed C++ compilers into their hand-grown "dynamic linking" environment, but usually by that point you are better off with using a language where that is a built-in feature, or not using the raw C++ object model and using something reflection-enabled.
It is quite likely that the underlying problem you are trying to solve using this technique can be solved in C++, if one exists.
I have a third party library as source code. It comes with a Visual Studio project that builds a .lib from it.
I want to access the functionality from C# though, so I copied the project and changed it to create a dll.
The DLL didn't contain any exported functions though, so I also created a module definition (.def) file, and added the functions I need in the EXPORTS section.
This works for all the functions that are declared in extern "C" blocks. However, some of the functions that I need are declared outside of those blocks.
If I add those to the EXPORTS section I get the error LNK2001 unresolved external symbol XYZ :(
I don't want to change the sourcecode of the 3rd party library if I can avoid it.
What's the most elegant and hopefully simplest way to access those functions as well?
Edit
One more point for clarification: As far I can tell there is no C++ functionality involved in the interface I want to expose. I honestly don't understand why the 3rd party authors did not just include the few remaining functions into the extern "C" blocks. These functions are at the bottom of the header file, maybe the person that added them just made a mistake and put them outside of the extern "C" blocks scope.
For C++ one way (IMHO the most elegant) would be using C++/CLI, which is designed for that. Especially if you have not only functions but also classes.
You create a thin wrapper layer which is fairly simple:
Create a CLI class
put a member instance of the original class
wrap all public methods from the original class
Like This (untested):
C++ nativ:
// original c++ class
class Foo {
public:
Foo(int v) : m_value(v) {}
~Foo() {}
int value() { return m_value; }
void value(int v) { m_value = v; }
private:
int m_value;
};
CLI wrapper:
// C++/CLI wrapper
ref class FooWrap
{
public:
FooWrap(int v) { m_instance = new Foo(v); }
!FooWrap() { delete m_instance; }
~FooWrap() { this->!FooWrap(); }
property int value {
int get() { return m_instance->value(); }
void set(int v) { m_instance->value(v); }
}
private:
Foo *m_instance;
};
Here you can find a short howto, which describes it in more detail.
Edit:
From your comments:
[...] I never worked with C++/CLI though and the language looks a little confusing. Since the project deadline is pretty close I'm not sure if there's enough time to learn it. I'll definitely keep this option in mind though!
If you are not looking for the most elegant way, as in your original question, but for the fastest/shortest way: For C++ one way (IMHO the shortest way) would be using C++/CLI, which is designed for that. Especially if you have not only functions but also classes. You create a thin wrapper layer which is fairly simple... Here you can find a short (in 10 min) howto, which describes it in more detail.
I'm new to C++ and new to codelite and also new to wxCrafter. I'm trying to build some GUI apps, but I'm messed up about object passthrough in C++. I spent a few hours and I just understand a little bit of that. First, to pass variables between wxFrame/wxDialog, I should create a instance of that class.
in frameA.cpp
void frameA::buttonAClicked() {
frameB * frameB1 = new frameB(NULL);
frameB1->connect(this);
}
in frameB.cpp
void frameB::connect(frameA *upper) {
//now I can access frameA via upper
}
But for a more complex case(e.g. 10 frames), values entered by user need to be shared between frames. I think it's better to make the frames/dialogs to be handle by a parent. Since all classes were triggered by main.cpp, so I think MainApp() will be good idea. So I tried to do this:
main.cpp:
class MainApp : public wxApp {
public:
frameA * frameA1;
frameB * frameB1
//frameC, frameD, frameE etc.
MainApp() {}
virtual ~MainApp() {}
virtual bool OnInit() {
frameA1 = new frameA(NULL);
frameB1 = new frameB(NULL);
frameA1->connect(this);
frameB1->connect(this);
SetTopWindow(frameA);
return GetTopWindow()->Show();
}
};
in both frameA.cpp and frameB.cpp:
frameA::connect(wxApp *par) {
this->parent = par;
}
Now I'm able to access MainApp via parent, but the two member objects(one is itself) was not found. Am I missed something? I'm really new to C++. Is that any better way (or a formal way) to do?
There is convenient way to make kind of global data in wxWidgets application. Create file ApplicationData.h:
#pragma once // replace with #ifndef ... if not supported by your compiler
class frameA;
// place here required forward declarations
// ...
struct ApplicationData
{
frameA* frameA1;
// any other data you need
};
Include this file to application class h-file:
#include "ApplicationData.h"
class MainApp: public wxApp
{
public:
ApplicationData applicationData; // or may it private with get/set functions
...
};
Finally, you can access applicationData from any place of wxWidgets application:
ApplicationData* pData = &wxGetApp().applicationData;
// Set/read global data members here:
// pData->...
See also: wxGetApp function definition in wxWidgets reference: http://docs.wxwidgets.org/2.6/wx_appinifunctions.html Note that you must add IMPLEMENT_APP and DECLARE_APP macros to make it working.
After digging the web, I found some reference to a powerful pattern which exploits CRTP to allow instantiation at run-time of static members:
C++: Compiling unused classes
Initialization class for other classes - C++
And so on.
The proposed approach works well, unless such class hierarchy is placed into an external library.
Doing so, run-time initialization no more works, unless I manually #include somewhere the header file of derived classes. However, this defeats my main purpose - having the change to add new commands to my application without the need of changing other source files.
Some code, hoping it helps:
class CAction
{
protected:
// some non relevant stuff
public:
// some other public API
CAction(void) {}
virtual ~CAction(void) {}
virtual std::wstring Name() const = 0;
};
template <class TAction>
class CCRTPAction : public CAction
{
public:
static bool m_bForceRegistration;
CCRTPAction(void) { m_bForceRegistration; }
~CCRTPAction(void) { }
static bool init() {
CActionManager::Instance()->Add(std::shared_ptr<CAction>(new TAction));
return true;
}
};
template<class TAction> bool CCRTPAction<TAction>::m_bForceRegistration = CCRTPAction<TAction>::init();
Implementations being done this way:
class CDummyAction : public CCRTPAction<CDummyAction>
{
public:
CDummyAction() { }
~CDummyAction() { }
std::wstring Name() const { return L"Dummy"; }
};
Finally, here is the container class API:
class CActionManager
{
private:
CActionManager(void);
~CActionManager(void);
std::vector<std::shared_ptr<CAction>> m_vActions;
static CActionManager* instance;
public:
void Add(std::shared_ptr<CAction>& Action);
const std::vector<std::shared_ptr<CAction>>& AvailableActions() const;
static CActionManager* Instance() {
if (nullptr == instance) {
instance = new CActionManager();
}
return instance;
}
};
Everything works fine in a single project solution. However, if I place the above code in a separate .lib, the magic somehow breaks and the implementation classes (DummyAction and so on) are no longer instantiated.
I see that #include "DummyAction.h" somewhere, either in my library or in the main project makes things work, but
For our project, it is mandatory that adding Actions does not require changes in other files.
I don't really understand what's happening behind the scene, and this makes me uncomfortable. I really hate depending on solutions I don't fully master, since a bug could get out anywhere, anytime, possibly one day before shipping our software to the customer :)
Even stranger, putting the #include directive but not defining constructor/destructor in the header file still breaks the magic.
Thanks all for attention. I really hope someone is able to shed some light...
I can describe the cause of the problem; unfortunately I can't offer a solution.
The problem is that initialisation of a variable with static storage duration may be deferred until any time before the first use of something defined in the same translation unit. If your program never uses anything in the same translation unit as CCRTPAction<CDummyAction>::m_bForceRegistration, then that variable may never be initialised.
As you found, including the header in the translation unit that defines main will force it to be initialised at some point before the start of main; but of course that solution won't meet your first requirement. My usual solution to the problems of initialising static data across multiple translation units is to avoid static data altogether (and the Singleton anti-pattern doubly so, although that's the least of your problems here).
As explained in Mike's answer, the compiler determines that the static member CCRTPAction<CDummyAction>::m_bForceRegistration is never used, and therefore does not need to be initialised.
The problem you're trying to solve is to initialise a set of 'plugin' modules without having to #include their code in a central location. CTRP and templates will not help you here. I'm not aware of a (portable) way in C++ to generate code to initialise a set of plugin modules that are not referenced from main().
If you're willing to make the (reasonable) concession of having to list the plugin modules in a central location (without including their headers), there's a simple solution. I believe this is one of those extremely rare cases where a function-scope extern declaration is useful. You may consider this a dirty hack, but when there's no other way, a dirty hack becomes an elegant solution ;).
This code compiles to the main executable:
core/module.h
template<void (*init)()>
struct Module
{
Module()
{
init();
}
};
// generates: extern void initDummy(); Module<initDummy> DummyInstance
#define MODULE_INSTANCE(name) \
extern void init ## name(); \
Module<init ## name> name ## Instance
core/action.h
struct Action // an abstract action
{
};
void addAction(Action& action); // adds the abstract action to a list
main.cpp
#include "core/module.h"
int main()
{
MODULE_INSTANCE(Dummy);
}
This code implements the Dummy module and compiles to a separate library:
dummy/action.h
#include "core/action.h"
struct DummyAction : Action // a concrete action
{
};
dummy/init.cpp
#include "action.h"
void initDummy()
{
addAction(*new DummyAction());
}
If you wanted to go further (this part is not portable) you could write a separate program to generate a list of MODULE_INSTANCE calls, one for each module in your application, and output a generated header file:
generated/init.h
#include "core/module.h"
#define MODULE_INSTANCES \
MODULE_INSTANCE(Module1); \
MODULE_INSTANCE(Module2); \
MODULE_INSTANCE(Module3);
Add this as a pre-build step, and core/main.cpp becomes:
#include "generated/init.h"
int main()
{
MODULE_INSTANCES
}
If you later decide to load some or all of these modules dynamically, you can use exactly the same pattern to dynamically load, initialise and unload a dll. Please note that the following example is windows-specific, untested and does not handle errors:
core/dynamicmodule.h
struct DynamicModule
{
HMODULE dll;
DynamicModule(const char* filename, const char* init)
{
dll = LoadLibrary(filename);
FARPROC function = GetProcAddress(dll, init);
function();
}
~DynamicModule()
{
FreeLibrary(dll);
}
};
#define DYNAMICMODULE_INSTANCE(name) \
DynamicModule name ## Instance = DynamicModule(#name ".dll", "init" #name)
As Mike Seymour stated the static template stuff will not give you the dynamic loading facilities you want. You could load your modules dynamically as plug ins. Put dlls containing an action each into the working directory of the application and load these dlls dynamically at run-time. This way you will not have to change your source code in order to use different or new implementations of CAction.
Some frameworks make it easy to load custom plug ins, for example Qt.
Solved
this wasn't the problem, since it's being implicitly cast to IFramework anyway.
I was concerned it may have to do with my methods not returning HRESULT, or with my stubby implementations of IUnknown::QueryInterface, but the real problem was merely a compiler setting that had overridden several macros I needed for common calling conventions (perhaps I should have included them in the question). This had corrupted the stack.
It's interesting though, that it worked will all compilers I tested, even without implementing IUnknown at all - a little research suggests that all serious Windows compilers handle abstract C++ interfaces the same way - namely as a virtual table specifically to be used as a COM interface.
Hi. I'm trying to create an extensible application framework. My basic concept is this:
The "Framework" box will build an .exe whereas the multiple "Plugin" boxes will build .dll files.
However, my implementation is apparently flawed. I have an idea what's the problem, but I'm running out of workarounds. I've done it exactly like this with .NET projects, but the problem I have now didn't apply to the C# environment.
Consider these interfaces:
class IFramework
{
public:
virtual void FrameworkMethod() = 0;
};
class IPlugin
{
public:
virtual void PluginMethod() = 0;
virtual void PluginCallbackTest() = 0;
virtual void SetFramework(IFramework *framework) = 0;
};
Implementation of the framework:
class CFramework : IFramework
{
public:
void FrameworkMethod(); // printf("FrameworkMethod");
void DoSomething(); // this is the testbench basically, see below
};
And the implementation of the plugin:
class CPlugin : public IPlugin
{
IFramework *Framework;
public:
void PluginMethod(); // printf("PluginMethod");
void PluginCallbackTest(); // Framework->FrameworkMethod();
void SetFramework(IFramework *framework); // Framework = framework;
};
// plugin factory -> COM interface
extern "C" PLUGIN_API IPlugin *GetPlugin(); // return new CPlugin;
Now to demonstrate that this concept doesn't work:
void CFramework::DoSomething()
{
HMODULE PluginHandle = LoadLibrary(...); // explicit linking
auto GetPlugin = ((IPlugin *)(*)())GetProcAddress(...);
IPlugin *plugin = GetPlugin();
plugin->PluginMethod();
// up until here everything's perfectly COM-compliant and works super
plugin->SetFramework(this); // <-- that is the problem
plugin->PluginCallbackTest(); // <-- runtime crash if compiler differs
FreeLibrary(PluginHandle);
}
The problem is that the SetFramework(this) doesn't work like COM. It's not that it just feels wrong to write it like this - I can't implement a working plugin with a compiler that differs from the one I used to build CFramework (runtime crashes).
If you want to allow different compilers for the plug-ins from what you use for the app then you need to use COM exclusively across the boundary between app and plug-ins. That is precisely the problem that COM was designed to solve.