I am doing some algorithmic work using C++. My algorithms have some options which I need to be able to add to my program with as little effort as possible. I am currently using this code.
Everything works as expected: I added some code to my program so I can call the binary with arguments like -oopt1=val1,opt2=val2 and the options are set automatically.
The problem is that I am also writing a GUI at the same time. Now every kind of option has to be able to be set/requested using the GUI. However, I might need a spinbox for an integer value and a check box for a boolean option. I am using Qt as a toolkit, so I could just write a member
function that returns a QWidget* which is the appropriate base class.
However, I do not want any GUI-specific code in the header where I declare my options, since I would like to separate the GUI from the rest of the program. I could subclass any Option to create an appropriate QWidget*, but if I get a list of OptBase*, I wouldn't know what kind of widget I should create.
Is there some way that I can keep the GUI separated from the rest of the program while still being able to create appropriate widgets?
For me the solution is to create an abstract factory :
The factory should have an interface with two abstract methods to createBoolOption and CreateChoiceOption. Possibly more methods are needed
You can then make two concrete implementations of this interface where one is returning the same ones as you are doing now, but when you are running in QT you can use a different implementation that returns an optbase derived class that does know how to create a widget.
You can even use multiple inheritance (ie a second interface) so that you don't have to create a method in the first interface to specifically create a widget.
Of course then in running the QT application you have to explicitely cast to the second interface, when you want to create the widget.
The abstract factory itself should be passed to constructor of algobase. Ie dependency injection.
class ifactory{
public:
virtual Option<bool>* createBoolOption()=0;
virtual ChoiceOption<Mode>* createChoiceOption()=0;
virtual Widget* createWidget()=0; //here or in another interface
};
class ConcreteNonGuiFactory : public ifactory{
virtual Option<bool>* createBoolOption();
virtual ChoiceOption<Mode>* createChoiceOption();
virtual Widget* createWidget()={;};
};
class ConcreteGuiFactory : public ifactory{
virtual Option<bool>* createBoolOption();
virtual ChoiceOption<Mode>* createChoiceOption();
virtual Widget* createWidget();
};
class Algo1 : public AlgoBase{
public:
Algo1(ifactory& f):factory(f){
ChoiceOption<Mode>* opt = factory.createChoiceOption();
}
private:
ifactory factory;
}
If the creation of the widget is in a different interface you can reduce your dependencies.
In this example at least the widget has to be forward declared.
You need a bunch of variables to be accessed by both setter (GUI, commang-line parser) and getter (algorithm function). QVariant should be fine. As you options have names, they also have implicitly types. Getter should retrieve the value by their name and explicitly make type conversion. Setter shouldn't care - QVariant will.
Create a singleton instance which has a map of option-names. Implement slots triggered by GUI value-change signals, set values in map.
e.g:
class VarTable
{
static VarTable & instance(){ static VarTable inst; return inst; }
QMap<QString, QVariant> _map;
public:
void setVar( QString n, QVariant v ){ _map[n] = v };
QVariant getVar( QString n ) const { return _map[n]; }
};
//Call in Slot triggered by a value-change signal (e.g. QEditLine::returnPressed)
VarTable::instance().setVal( "option1", val1 );
//Regrieve in non-gui code
QString option1 = VarTable::instance().getVal( "option1" ).toString();
Regards
P.S.: I've not compiled the code, mey have some typos.
Related
I'm writing an application that loads plugins, and each plugin acts as a factory for QObject subclasses. The application sends parameters to a plugin to instantiate an object, and each object uses different parameters to be created.
This is all working pretty well, however the parameters change between plugins and objects, and it would be nice if the application had a mode to report the parameters needed to construct an object. Objects are created by a config file, so the author of the config needs to know the required parameters to provide, especially if they change.
So I've been looking into Qt's MetaObject system, which is perfect for this use case, because I can create a message that will report the shape of an object's constructor using Q_INVOKABLE on the constructor and QMetaObject::constructor(int i).
The problem is that I have to use the actual class to get a QMetaObject static instance, and I would like to loop over a list of class names as strings to create this report.
I'm not interested in registering types for use with QVariant, because these objects aren't for copying around or sending over a network or serializing. They may be things connected to hardware or consume lots of memory. All I want is the constructor definition of a plugin's factory objects, but originating from the string name of each class the plugin can construct.
QObject instances provide a QMetaObject, but they don't seem to have an innate QMetaType, which is necessary for:
int typeId = QMetaType::type("MyClass");
const QMetaObject *s = QMetaType::metaObjectForType(typeId);
So instead I have to use
QMetaObject m = MyClass::staticMetaObject;
Which requires each definition to be manually coded into the plugin, as mentioned: How can I find a Qt metaobject instance from a class name?
Because QObject doesn't have a copy constructor, Q_DECLARE_METATYPE() will fail, as well as qRegisterMetaType(), and creating a fake copy constructor to satisfy the compiler is a bad idea, and requiring default constructors are bad as well in this use case.
If the solution is to manually type each class into a function providing this message to the config writer, then it is what it is. However if I'm missing a simpler solution, given that the plugin already provides a string list of available objects and acts as a factory for QObject subclasses (that don't have default constructors), I would like to learn it!
Does someone have a better idea how to do this:
QStringList p;
p << "MyClass";
p << "MyClass2";
for(int pi=0;pi<p.length();pi++)
{
int typeId = QMetaType::type(p[pi]);
const QMetaObject *s = QMetaType::metaObjectForType(typeId);
int c = s->constructorCount();
printf("constructor count: %d\n",c);
for (int i=0;i<c;i++)
{
QMetaMethod m = s->constructor(i);
printf("ctor %d: %s %s %d\n",i,qPrintable(m.name()),qPrintable(m.methodSignature()),m.parameterCount());
int nc = m.parameterCount();
QList<QByteArray> pn = m.parameterNames();
QList<QByteArray> pt = m.parameterTypes();
for (int j=0;j<nc;j++)
{
printf("\t%s %s\n",qPrintable(pt.at(j)),qPrintable(pn.at(j)));
}
}
}
This will crash because typeId == QMetaType::UnknownType, and therefore s == null.
Ultimately, manually coding each entry was my solution.
I have a set of interfaces that can be implemented by plug-ins in a Qt
application. Every plug-in must implement at least one common
interface, called Base_plugin, to provide some basics (description,
name, etc.). When calling a specific plug-in interface I often have to
get this basic to present it in the user interface. This leads to a
lot of code like:
Foo_plugin* p = getSuitableFooPlugin();
// cannot use qobject_cast, plug-in interfaces don't derive QObjects
Base_plugin* b = dynamic_cast<Foo_plugin*>(p);
setName(b->name());
p->getAction();
This works at least on gcc, but I'm afraid that this is not going to
work on Windows. Alternatively I could use reinterpret_cast or store
pointers of the correct type to each plug-in when loading them (I have
a valid QObject* there). Neither of those solutions seems really
clean to me.
Is there a better way around this problem?
As I understand, you have smth like this (if you don't, think about refactor to make it like this)
struct IBase
{
virtual QString name() const = 0;
virtual void setName(const QString name&) = 0;
};
Q_DECLARE_INTERFACE(IBase, "best.app.ever.plugins.base");
struct IFoo
{
virtual void foo() = 0;
};
Q_DECALRE_INTERFACE(IFoo, "best.app.ever.plugins.foo" );
struct Plugin: QObject, IBase, IFoo
{
Q_OBJECT()
Q_INTERFACES(IBase)
Q_INTERFACES(IFoo);
//....
};
Q_EXPORT_PLUGIN2(best_app_ever, Plugin);
now when you load plugin, you get an QObject and you shoud use qobject_cast to cast this QObject to your interface classes.
Specializations of qobject_cast that process casting to your interfaces get created automatically by Q_DECLARE_INTERFACE macroses.
Perhaps I'm not getting it right, but can't you just write:
Foo_plugin* p = getSuitableFooPlugin();
setName(p->name());
p->getAction();
Since Foo_plugin inherits from Base_plugin, and if Base_plugin::name() is public, you can call it without casting.
Here is what i am trying to do.
I have Three Classes:
1) CEngine
2) CLogManager
3) CWindowGL
Ad1.
This class 'does' the tricky things to get the game engine going,
an application utilizing it, can call only few public members to
get the game going -
class CEngine
{
public:
CEngine();
~CEngine(); // should this go to private?
bool Init(width,height,...);
void Destroy();
void Run();
bool LoadMap(...);
private:
CLogManager *m_pLogManager;
CWindowGL *m_pWindowManager
}
// Example usage
CEngine *Engine=new CEngine;
Engine->Initialize(...)
Engine->LoadMap(...)
Engine->Run()
Engine->Destroy()
delete(Engine)
Ad2.
This class controls the logging facility
it just allows me to dump some log into the log data file:
class CLogManager
{
public:
CLogManager();
~CLogManager();
void Write(const char *fmt,...);
private:
FILE *fp;
std::string m_sFileName; // unique filename generated at the constructor
SYSTEMTIME m_tSystemTime;
}
Ad3.
This class handles the window creation, and pixel format settings,
and few other things related to the window itself - nothing else,
but it also needs to utilize CLogManager - to dump few informations
for debug purposes.
Now the question is:
When a CLogManager constructor is called, class generates a unique filename that is:
m_sFileName="data/logs/enginelog_%i%i%i.txt"; // hour, minute, second
CEngine class in the Init method does:
m_pLogManager = new CLogManager;
and later on it uses it with m_pLogManager->Write(....) to log events.
That's ok for CEngine, but i would like to use the same functionality
in CWindowGL class and here is the question.
I would like my code to share CLogManager across :
CEngine
CWindowGL
...
...
...
and few others that i'll implement.
I can't do this by adding "Instance()" type of method like:
static CLogManager &Instance()
{
static CLogManager s_instance;
return s_instance;
}
and calling:
CLogManager::Instance().Write(" LOG MESSAGE ");
As this would cause my CLogManager to generate new filename each time when a
constructor is called.
Do i have to
extern CEngine *Engine;
somewhere to call
Engine->Log(" LOG MESSAGE ")
wrapper everytime or there is something else i can stick to?
I know it is more like a 'code-design' question, but i would like to see
how do you guys handle such things.
Normally i would do this with extern, but that would require me to check
m_pLogManager!=NULL within a wrapper function to a private member - and just
don't know if that's OK.
Maybe there's some other - better approach?
I will be adding few other classes like. TexturesManager - and would like this class to
store the actual size of textures loaded and so on, so this would also require me to
not to call Instance() to class each time the texture is called - as this would create/destruct the class without storing the needed size / array of textures already loaded...
Uff..
Thanks, hope this is clear.
I can't do this by adding "Instance()" type of method as this would cause my CLogManager to generate new filename each time when a constructor is called.
Actually no, the constructor would be called only once during your program lifetime. The singleton pattern is what you most likely want for your logging class.
What you'll generally find in these situations is a static set of methods that use a singleton underneath. All consumers call the static method which returns the one, single, instance of your logger, which you then call methods on.
I certainly don't know how to title this question, sorry.
I'm having some problems to design the following system.
I need a class which will make some work, but this work can be done in a bunch of different ways, say that this work will be made through "drivers".
These drivers can have different interfaces and because of that I need to build a wrapper for each driver.
So I got (or I need) this:
Me ---> MainClass ----> Wrapper ----> Drivers
MainClass is the class I will touch and will call the drivers methods through different wrappers.
Here an example of usage:
MainClass worker;
worker.set_driver("driver_0");
worker.start_process(); //Start process calls a wrapper method which calls a driver's method.
To achieve this I made an interface class:
class Driver_Interface : public QObject
{
Q_OBJECT
public:
Driver_Interface(QObject* parent=0) : QObject(parent){}
virtual bool open()=0;
virtual bool close()=0;
virtual bool write()=0;
virtual bool set_config()=0;
};
A driver wrapper has this shape:
class Driver0 : public Driver_Interface
{
Q_OBJECT
public:
Driver0( QObject* parent=0);
Driver0();
bool open();
bool close();
bool write();
bool set_config();
};
Finally here comes the conflicting point, defining the MainClass:
I would like to avoid to create one member for each wrapper, so I tried this, and right now compiler doesn't complains:
class MainClass
{
public:
MainClass();
~MainClass();
void init();
void set_driver( const QString& );
void start_process();
protected:
QString driver_str;
Driver_Interface* driver; //!<--- Here Here!!!
};
When setting the driver chosen, I do this:
if( driver_str.compare("driver_0")==0 )
this->driver = new Driver_0();
Is this a valid C++ configuration or will I have problems sooner or later?
Basically, what worries me is the creation of the driver of a different type from Driver_Interface, I'm seeing that it casts automatically and no one complains...
Actually I have some problems now compiling, the infamous vtables not defined in Driver_0... does this have some relation with what I want to achieve? UPDATED: I fixed this by deleting the *Driver_Interface* constructor.
To me your basic idea seems to be fine. I would consider separating the creation of drivers into a factory (or at least a factory method) though.
This seems reasonable to me. Having a FactoryMethod or class (AbstractFactory) that creates an object of the required concrete subclass based on some config value is a common pattern.
You could consider having the MainClass implement something like
DriverInterface* createDriver(const string& driverType)
instead of encapsulating the resulting concrete DriverInterface subclass in MainClass. But if you only ever want one concrete DriverInterface instance, the above looks fine.
I would pass "driver_0" to the constructor, and call MainClass::set_driver from there. You can then make MainClass::set_driver private unless you need to change drivers.
I have a list of Parts and some of them need a pointer to an Engine, lets call them EngineParts. What I want is to find these EngineParts using RTTI and then give them the Engine.
The problem is how to design the EnginePart. I have two options here, described below, and I don't know which one to choose.
Option 1 is faster because it does not have a virtual function.
Option 2 is easier if I want to Clone() the object because without data it does not need a Clone() function.
Any thoughts? Maybe there is a third option?
Option 1:
class Part;
class EnginePart : public Part {
protected: Engine *engine
public: void SetEngine(Engine *e) {engine = e}
};
class Clutch : public EnginePart {
// code that uses this->engine
}
Option 2:
class Part;
class EnginePart : public Part {
public: virtual void SetEngine(Engine *e)=0;
};
class Clutch : public EnginePart {
private: Engine *engine;
public: void SetEngine(Engine *e) { engine = e; }
// code that uses this->engine
}
(Note that the actual situation is a bit more involved, I can't use a simple solution like creating a separate list for EngineParts)
Thanks
Virtual functions in modern compilers (from about the last 10 years) are very fast, especially for desktop machine targets, and that speed should not affect your design.
You still need a clone method regardless, if you want to copy from a pointer-/reference-to-base, as you must allow for (unknown at this time) derived classes to copy themselves, including implementation details like vtable pointers. (Though if you stick to one compiler/implementation, you can take shortcuts based on it, and just re-evaluate those every time you want to use another compiler or want to upgrade your compiler.)
That gets rid of all the criteria you've listed, so you're back to not knowing how to choose. But that's easy: choose the one that's simplest for you to do. (Which that is, I can't say based of this made-up example, but I suspect it's the first.)
Too bad that the reply stating that 'a part cannot hold the engine' is deleted because that was actually the solution.
Since not the complete Engine is needed, I found a third way:
class Part;
class EngineSettings {
private:
Engine *engine
friend class Engine;
void SetEngine(Engine *e) {engine = e}
public:
Value* GetSomeValue(params) { return engine->GetSomeValue(params); }
};
class Clutch : public Part, public EngineSettings {
// code that uses GetSomeValue(params) instead of engine->GetSomeValue(params)
}
Because GetSomeValue() needs a few params which Engine cannot know, there is no way it could "inject" this value like the engine pointer was injected in option 1 and 2. (Well.. unless I also provide a virtual GetParams()).
This hides the engine from the Clutch and gives me pretty much only one way to code it.