I've often come across APIs that allow users to get and set various parameters that control a module's operation. I now find myself contemplating writing yet another properties API but don't want to reinvent the wheel.
The following is typical basic client code:
setInt("bitrate", 1000);
setEnum("mode", MODE_FAST);
setStr("output file", "music.mp3");
Frequently there are dozens of parameters that can be set and such property sets are often under continuous development.
Some APIs are smarter than others, more advanced features being:
Hierarchical grouping of properties
Enumeration of properties
Numeric parameters with enforced minima and maxima
Default parameter values
Settings that are enabled, disabled or read only
Dynamic parameters - settings that appear, disappear, have min/max set, become enabled, disabled or read only depending on other parameters' state.
Properties accessed via UUID key rather than textual name
Beyond the C-style accessors in the sample code above, I've come across frameworks that can:
Read/write properties to file (e.g. XML)
Read/write settings to Windows Registry
Interface with system properties APIs like IPersistPropertyBag
Have default dumb GUI implementations, e.g. tree-view or list
Have GUI extensions appropriate to minima/maxima/enabled state reducing repetition in GUI code.
I would love to find a well-designed public library that provides a framework for all of the above but so far have drawn a blank. I'm aware of Boost.PropertyTree but it's only really a skeleton. Are there other portable properties API frameworks that I should be aware of?
One of the key elements of the Qt property system is actually a very solid implementation of a variant type class QVariant that enables you to get rid of the typed setInt, setString ... calls.
If you get a hold of a similar well behaved class e.g. possibly Boost::Variant or something similar a property system is fairly easy to implement using a map of string as the backing part.
One of the conveniences of the qt property system is that you can override setter and getter functions without the user having to know about them. E.g. given your generic property setter being setProperty(name, value). The implementor can in the class declaration denote that the property "speed" has its own setter setSpeed(float value) so that when a user of your class invokes the generic version of setProperty("speed", 100), the system will call setSpeed(100) on your instance.
If you don't need features like that you can probably implement your own property system. Gamasutra has a piece on implementing reflection in C++ that might help you too.
If you don't mind having a dependency on Qt Core, then Qt has a fairly well designed property system. This means though that you will be relying on Qt's MOC.
Related
The aeron_udp_channel_transport_stct::bindings_clientd is only found be used in aeron_udp_channel_transport_init function which set the bindings_clientd to NULL without further operations. Except some modification and assert in test cases.
In the test case, it is assigned as struct aeron_test_udp_bindings_state_stct, which containes some state counter.
What role does this data member play in Aeron? What is the proper usage of bindings_clientd?
TL;DR unless you are writing a custom network binding don't concern yourself with this field.
The Aeron C driver has support for adding different network bindings implementations (see aeron_udp_channel_transport_bindings_stct). In the OSS repo there is only support for traditional OS (Linux, Mac, Windows) networking. However, if a user wanted to add an additional implementation that used a different network API and needed to carry some implementation specific information on each transport instance, this would be the field to add it to. In theory for the UDP implementation, it could be refactored towards having a structure that held the file descriptors here.
The test driver carries some state information in that field so that behaviour can be asserted within the tests. There also exists commercial extensions to the C driver (e.g. for DPDK) that make use of this field too.
Before April 2019, it was possible for a Lua script to reflect the methods and properties of a LuaBridge class using string keys __parent, __class, __propget, and __propset. This was an incredibly useful tool for creating test scripts and development tools to maintain a large class framework exported into Lua.
From looking through the release notes of LuaBridge, it seems the string keys were removed for security reasons. But I find myself placing more priority on the ability to reflect classes from scripts than on whether scripts can muck around in the object model. Especially in dev mode.
The LuaBridge Reference Manual implies there is a way for a C/C++ program to expose the metatables, but I haven't been able to figure out how to do it. I am quite new to interfacing between C and Lua (or LuaBridge), so I'm not surprised that I am perplexed. If anyone could share an example of how to do this, I would appreciate it.
Since no one seems to have a good suggestion, I realized I could roll my own reflection of the names of properties, methods, and constants. For my purposes I don't really need to execute or access them.
So rather than muck around inside LuaBridge I added __class, __propget, and __propset static properties to every class in my framework. These return a table implemented with std::map which LuaBridge supports. The tables simple have the names as keys and a dummy value.
One caveat I discovered is that you have to add static properties to derived classes when creating the derived class with deriveClass. If you try to add them later (using beginClass), LuaBridge throws an assert.
I would like to develop relatively simple dialog-based GUIs for Raspberry PI 2 (Linux/Raspbian) that is why would like to study Qt beginning with the basic/core features. RTFM, I know. So I read one of them, and to be honest understood very little.
The biggest question in my head: Why would it have been worth reading in the first place? What is the purpose of the Qt properties? What are they good for?
How do they work internally and from the point of view of writing the code.
What is the memory and performance cost? Is it necessary to use them? If not, is it worth using them considering my use case?
Properties are used to read/write values in objects through a standard generic interface. Needed for interfacing with script engines (QtScript or QtQml), the widget designer, remote object interfaces (QtDBus, QtRemoteObjects, QtWebChannel).
Most properties get implemented through normal getter/setter functions which are then tied to a property name and registered with the property system using the Q_PROPERTY macro. Alternatively the property name can be bound to a member variable. Read/write access with the generic property() and setProperty() API is the rerouted either to calls to the registered getter/setter or to the registered member variable.
The property information is stored as a QMetaProperty in the class' staticMetaObject, access through the property API will incur a lookup based on the property name.
Your use case doesn't seem to require usage of properties.
Another use case, as mentioned by Kuba in the comment, is to attach data to QObject based objects without modifying them.
These kind of properties, so called "dynamic properties", are handled slightly differently. Instead of getter/setter functions or a member variable, they are stored in a generic internal storage, currently a QVector<QVariant>
For example, an empty QObject-based class defined in C++. It's created from QML. Then C++ adds some properties to it via setProperty. But they aren't becoming accessible by QML.
Other example: use setContextObject and then start adding properties to that C++ object. No effect on QML.
How to make it work?
update
I see two options: private API (MetaObject builder) and code generation for QML items at runtime.
I think you're looking for QQmlPropertyMap. It allows you to add properties dynamically. It's usually better to predefine values through qt models in C++ though, and there aren't many good use cases for using QQmlPropertyMap.
There actually several ways to do this, this article has a great explanations.
The DYNAMIC FACTORY pattern describes how to create a factory that
allows the creation of unanticipated products derived from the same
abstraction by storing the information about their concrete type in
external metadata
from : http://www.wirfs-brock.com/PDFs/TheDynamicFactoryPattern.pdf
The PDF says:
Configurability
. We can change the behavior of an application by just changing its configuration
information. This can be done without the need to change any source code (just change the descriptive information about the type in the metadata repository) or to restart the application (if caching is not used – if caching is used the cache will need to be flushed).
It is not possible to introduce new types to a running C++ program without modifying source code. At the very least, you'd need to write a shared library containing a factory to generate instances of the new type: but doing so is expressly rules out by the PDF:
Extensibility / Evolvability
. New product types should be easily
added without requiring neither a
new factory class nor modifying
any existing one.
This is not practical in C++.
Still, the functionality can be achieved by using metadata to guide some code writing function, then invoking the compiler (whether as a subprocess or a library) to create a shared library. This is pretty much what the languages mentioned in the PDF are doing when they use reflection and metadata to ask the virtual machine to create new class instances: it's just more normal in those language environments to need bits of the compiler/interpreter hanging around in memory, so it doesn't seem such a big step.
Yes...
Look at the Factories classes in the Qtilities Qt library.
#TonyD regarding
We can change the behavior of an application by just changing its configuration information.
It is 100% possible if you interpret the sentence in another way. What I read and understand is you change a configuration file (xml in the doc) that gets loaded to change the behaviour of the application. So perhaps your application has 2 loggers, one to file and one to a GUI. So the config file can be edited to choose one or both to be used. Thus no change of the application but the behaviour is changed. The requirement is that anything that you can configure in the file is available in the code, so to say log using network will not work since it is not implemented.
New product types should be easily added without requiring neither a new factory class nor modifying any existing one.
Yes that sounds a bit impossible. I will accept the ability to add ones without having to change the original application. Thus one should be able to add using plugins or another method and leave the application/factory/existing classes in tact and unchanged.
All of the above is supported by the example provided. Although Qtilities is a Qt library, the factories are not Qt specific.