variable global const "macros" in C++ and optimal design patterns - c++

I inherited some 10 year old code I have to complete. The code is in MFC (C++).
There's a .h file where the custom data structures are written and some const variables are in there as Globals. Some of these are used for MS Office file extensions, of type CString, and are declared as _T(".doc"), _T(".xls"), etc.
Obviously these are dated and need to be updated to recognize the Office 2007 and later extensions. My first brilliant idea was to use const_cast to change the constant if needed, but found out later that's a no-no and resulted in undefined behavior (sometimes it would switch back to .doc).
I then decided to create a struct and have two structs inherit from it. I created a void method in the base struct to make it abstract but otherwise it does nothing. Here's the code:
struct eOfficeExtensions{
const CString WORD_EXTENSION;
const CString EXCEL_EXTENSION;
const CString WORDPAD_EXTENSION;
const INT EXTENSION2007;
eOfficeExtensions(CString word, CString excel, CString wordpad, INT ver) :
WORD_EXTENSION(word), EXCEL_EXTENSION(excel), WORDPAD_EXTENSION(wordpad), EXTENSION2007(ver){}
//method to ensure base class is abstract
virtual void Interface() = 0;
};
struct eOfficeExtensions2003 : public eOfficeExtensions{
public:
eOfficeExtensions2003() : eOfficeExtensions(_T(".doc"), _T(".xls"), _T(".rtf"), 0){}
private:
virtual void Interface(){}
};
struct eOfficeExtensions2007OrLater : public eOfficeExtensions{
eOfficeExtensions2007OrLater() : eOfficeExtensions(_T(".docx"), _T(".xlsx"), _T(".rtf"), 1){}
private:
virtual void Interface(){}
};
This feels like a ridiculous amount of code for what should be a simple conditional definition. What would an experienced programmer do?
EDIT
These constants should only be set once and never changed. The version of MS Office installed is determined by scanning registry subkeys in a class that deals with memory management.
The constants are mainly used to create new files or search a directory for files with that extension, not for resolving conditional statements. The struct should also be instantiated once as a eOfficeExtensions* pointer to the relevant child struct.

Your inheritance tree essentially defines two different values for the base struct.
You don't need inheritance just to define those values, you only need two variables:
struct eOfficeExtensions{
const CString WORD_EXTENSION;
const CString EXCEL_EXTENSION;
const CString WORDPAD_EXTENSION;
const INT EXTENSION2007;
};
const eOfficeExtensions extensions2003{_T(".doc"), _T(".xls"), _T(".rtf"), 0};
const eOfficeExtensions extensions2007{_T(".docx"), _T(".xlsx"), _T(".rtf"), 1};
const eOfficeExtensions* extensions = 0;
// ... Later ...
if (office2007Installed)
extensions = &extensions2007;
else
extensions = &extensions2003;

Related

How to design libraries to create debugging applications over them?

The Problem
I want to create a debugging application over my libraries for testing, debugging, ... purposes. But I don't want to give the end-user additional non-necessary APIs.
For example, consider an application that visualizes the program's plugin usage of the library to the end-user. So I can't use standard debuggers like GDB or LLDB with a Release build containing some debugging information. How could be the library/debugging application designed for that?
The Restrictions
Must work on Windows(MSVC-2015) and Linux(GCC-8).
C++11 only.
No debug information.
No core dumps.
No additional public APIs.
The Requirements(If It's Possible)
Accessing the library's main class private members without additional public/protected APIs I think could be enough if there is no other way to do it.
Possible Solution
I just introduce an additional symbol into my main library class as the class friend:
Complete code: MyLibrary.hh
class MyClassPrivate;
class MyClass {
public:
friend class MyClassDebugger;
int value() const;
private:
friend class MyClassPrivate;
std::unique_ptr<MyClassPrivate> impl_;
};
And then I export the class header and the class private header to the user and the user could just define the MyClassDebugger symbol and use it to access to the MyClass private implementations:
Complete code: main.cc
class MyClassDebugger {
public:
void modify(MyClass& object)
{
object.impl_->value = 100;
}
};
int main()
{
MyClass object;
MyClassDebugger().modify(object);
std::cout << object.value() << std::endl;
}
The complete code of the example: https://gist.github.com/gccore/397fb6147280bd32b6fe340aa6ce579a
I would consider dropping your “No additional public APIs” requirement, and implement some reflection interface for your objects, which allows users to list properties exposed to debug interface, get property values, and update these values. Here’s an example how that API may look like.
// Change this enum to contain types of various properties you have in your classes
// For instance, if you don't have nested objects, remove the corresponding entry from the enum
enum struct ePropertyType: uint8_t
{
Empty = 0,
Int32,
FP32,
String,
NestedObject
};
struct iDebugView;
// Variant structure for the values
struct sPropVariant
{
// The type of the value
ePropertyType type = ePropertyType::Empty;
// The value itself
union
{
int int32;
float fp32;
const char* string;
iDebugView* nestedObject;
};
};
// Describes a single field of some particular type
struct sPropertyDesc
{
std::string name;
ePropertyType type;
};
// Debugger interface to view and change private fields of objects
struct iDebugView
{
// Get descriptor for all properties exposed by this object.
// Note this doesn't include the values i.e. only depends on the object's type but not the instance
// Your implementation should return reference of a global variable, possibly lazily initialized on first use
virtual const std::vector<sPropertyDesc>& listProperties() const = 0;
// Get value of the property identified by 0-based index
// Returns ePropertyType::Empty if the index was out of range
virtual sPropVariant getValue( uint32_t index ) const = 0;
// Set value of the property identified by 0-based index.
// Returns false for errors such as index out of range, type mismatch, or trying to set NestedObject property
virtual bool setValue( uint32_t index, const sPropVariant& value ) = 0;
};
While not terribly complicated, that new API should enable GUI similar to PropertyGrid in C#, allowing to inspect and modify private properties of your classes.

Invoking non static class member function of dynamically loaded library

I am writing an app with optional runtime dependency with KWallet. It means if there is KWallet installed on user system it's used and if not it still works but without KWallet support.
Here is how I load the library, it's a static property of my wrapper class. Then in the constructor under condition of state I resolve symbols from the library.
QLibrary Core::PSE::KWallet::lib("KF5Wallet");
...
lib.load();
openWallet = (OpenWallet) lib.resolve("_ZN7KWallet6Wallet10openWalletERK7QStringyNS0_8OpenTypeE");
networkWallet = (NetworkWallet) lib.resolve("_ZN7KWallet6Wallet13NetworkWalletEv");
destructor = (Destructor) lib.resolve("_ZN7KWallet6WalletD2Ev");
The same as the QLibrary - function are also static members of my class, but I'm not sure if that's a good idea.
Here are definitions from my class
typedef ::KWallet::Wallet* (*OpenWallet)(const QString &, WId, ::KWallet::Wallet::OpenType);
typedef QString (*NetworkWallet)();
typedef void (*WalletOpened)(bool);
typedef void (*Destructor)();
static OpenWallet openWallet;
static NetworkWallet networkWallet;
static Destructor destructor;
Here is how I allocate an object
wallet = openWallet(networkWallet(), 0, ::KWallet::Wallet::Asynchronous);
Everything goes fine until the point I need to execute non static members and, especially, destructor. As far as I know, it is supposed to look like that
((*wallet).(destructor))()
but that doesn't seem to work. I'm totally new to this topic and I have no idea even if I had started in a right way.
So, how do I invoke the destructor of this way loaded class? How do I invoke the rest of it's members? Or shall I better do it in some completely other way?
P.S. I'm aware, there is a DBUS API for KWallet, even some wrapper libraries like qtkeychain, but I want to understand the way of making this kind of dependencies using this example.
I have found the solution.
The idea is to write a small shared library with wrapper functions like that
extern "C" KWallet::Wallet* openWallet(const QString &name, WId w, KWallet::Wallet::OpenType ot = KWallet::Wallet::Synchronous) {
return KWallet::Wallet::openWallet(name, w, ot);
}
extern "C" void deleteWallet(KWallet::Wallet* w) {
w->deleteLater();
}
extern "C" const char* networkWallet() {
return KWallet::Wallet::NetworkWallet().toStdString().c_str();
}
extern "C" int readPassword(KWallet::Wallet* w, const QString &key, QString &value) {
return w->readPassword(key, value);
}
Let's call this little wrapper foo.so. So, then you build this foo.so and target link at build time to the real dependency, KWallet in my case.
Then in the main code you're going to try dynamically load this foo.so, not the KWallet itself. And if the KWallet is absent on the launching machine this foo.so is simply not going to load, that's the trick I had to know!
Then of course you simply resolve symbols like this
QLibrary Core::PSE::KWallet::lib("foo");
...
lib.load();
openWallet = (OpenWallet) lib.resolve("openWallet");
networkWallet = (NetworkWallet) lib.resolve("networkWallet");
deleteWallet = (DeleteWallet) lib.resolve("deleteWallet");
readPassword = (ReadPassword) lib.resolve("readPassword");
And call it like this
wallet = openWallet(networkWallet(), 0, ::KWallet::Wallet::Asynchronous);
...
QString password;
int result = readPassword(wallet, *i, password);
...
deleteWallet(wallet);
Before going into solution I should state that this is very bad idea and I can't see a sensible reason to go this way except if you are using a class from a compiled shared library which you can't edit its source and the class has no alternative virtual interface .
The better way to do this in c++ is to use virtual methods by making a base class containing the functionality you need to use and any subclass in a shared library can override those virtual methods to customize the behaviour .
Now this is the solution to your case :
A non static method of a class has a calling convention of thiscall which means that they are like ordinary functions except they take a pointer to the class instance as the first argument , this is the this pointer ! In fact methods in c++ (non virtual) are syntactic sugar for c functions which operate on a struct
This snippet of code illustrates :
struct somestruct
{
int j;
};
void add(somestruct* this, int i)
{
this->j += i;
}
class someclass
{
public:
void add(int i)
{
j += i;
}
private:
int j;
};
So in your case : for each method declaration add a pointer to the class instance that is the first argument and when you want to call this method on an instance just pass it as the first pointer.
Virtual functions are implemented in two ways :
1 - a vtable inside the class itself like c vtables
2 - a pointer to vtable inside the class so you only have one vtable per class declaration and it's said that this method is better for cache hence it's used by most compilers

Char array initialisation in class

I am trying to unit test a C++ application that I am building and I'm having an issue initializing the array when used in a class. I've tried alot of different methods of loading this information, the only ones that work are inefficient / not suitable.
Here is the hex array that I have (randomised the parts)
0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10
And header file for my unit test:
class MessageParsingTest : public CPPUNIT_NS::TestFixture {
CPPUNIT_TEST_SUITE(MessageParsingTest);
CPPUNIT_TEST(testIdentifyFirstMessageType);
CPPUNIT_TEST_SUITE_END();
public:
MessageParsingTest();
virtual ~MessageParsingTest();
void setUp();
void tearDown();
private:
void testIdentifyFirstMessageType();
void testIdentifySecondMessageType();
// data members for the hex array
unsigned char firstMessage[1500];
};
Then in my test case setUp function;
void MessageParsingTest::setUp() {
firstMessage = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
}
That it my latest failed attempt, it says its not valid during compilcation, as I expected, but at this point I was trying anything.
I've also tried things like (all in setUp function)
firstMessage << "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
firstMessage[1500] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
and a few other crazy ways, Does anyone know the proper way to load this data? the only way I've had it working so far is with either no data member declaration and straight up defining it and initializing in one line (but then I cant access in the test cases) or doing it one by one like firstMessage[0] = 0x24; etc.
I understand that there will be a simple, proper way of doing this and considering what the application actually does, this part should be the easiest.
You have few options:
Initialize arrays in constructor MesssageParsingTest using syntax : firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10}
in initializer list.
Create static const array containing your message, and either copy it to member variable using memcpy, or use static member and get rid of firstMessage member variable.
Declare const static member in .h inside class definition:
static const unsigned char kFirstMessage[];
and define + initialize it in .ccp
const unsigned char MessageParsingTest::kFirstMessage[] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
I would prefer static const member if you do not intend to modify this array later, since it makes the intention cleaner.
Here is one way to do it.
void MessageParsingTest::setUp()
{
unsigned char x[] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
::memcpy(firstMessage, x, sizeof(x));
}
If you are using C++11, you can also initialize the firstMessage in the class member initialization list as
MessageParsingTest::MessageParsingTest() :
firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10},
...
You can use a temporary buffer and then copy into you member as this:
void MessageParsingTest::setUp() {
unsigned char tmp[1500] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
memcpy(firstMessage, tmp, 1500);
}

const correctness for configuration structures

I have a configuration file which gets read in, parsed and put into structures at the beginning of my programs run time.
The problem I am having is that I want these structures to be constant since the values in them should not change during the programs lifespan.
Currently I am doing the following:
config.h
#pragma warning(push)
#pragma warning(disable: 4510) /*-- we don't want a default constructor --*/
#pragma warning(disable: 4610) /*-- we don't want this to ever be user instantiated --*/
typedef struct SerialNode {
private:
void operator=(SerialNode&);
public:
const char* const port;
const char* const format;
} SerialNode;
#pragma warning(pop)
typedef std::map<const char*, const SerialNode*, MapStrComp> SerialMap;
SerialMap SerialConfig;
config.cpp
/*-- so we don't fall out of scope --*/
SerialNode* global_sn;
SerialNode local_sn = {port, format};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
This works fine. However my problem is that now I am dealing with more complicated configuration data which requires me to pull a structure back out of the list, modify it and then put it back.
Obviously I can't modify it, so the solution would be something like:
SerialNode* global_sn;
SerialNode* old_sn = SerialConfig[key_store];
SerialNode local_sn = {port, format, old_sn->old_data, old_sn->more_old_data};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
delete old_sn;
But this strikes me as bad programming practice. Is there is a better way to achieve what I'm going for which doesn't require such a hacked looking solution?
For reference, I'm using Visual Studio 2010
As always, the best thing you can do is not re-implement something that has already been written. There are a large number of libraries and frameworks that will help with serialization for c++:
Boost Serialization
Qt
Protocol Buffers
msgpack
Capn' Proto
Ideally the serialization framework you choose will exactly recreate the data graph that you are trying to store. Regardless of whether you have done any fixup, your goal will likely be to only provide const access to the global configuration data. Just make sure that mutators (including non const pointers) are not exposed via a header file.
The simple answer is what Thomas suggest, but correctly done (that is, not causing undefined behavior):
Create a mutable configuration object but pass it to the rest of the components by constant reference. When you create (and where you maintain) the real object you can change it, but the rest of the application won't be able to modify the config. A common pattern I have used in the past was:
class SomeObject {
Configuration const & config;
public:
SomeObject(Configuration const & config) : config(config) {}
void f() {
if (config.someParam()) { ...
// ...
void loadConfiguration(Config & config) { ... }
int main() {
Configuration config;
loadConfiguration(config); // config is a non-const &, can modify
SomeObject object(config); // object holds a const&, can only read
object.f();
// ...
This is not an answer to your question, just some observations to your code.
You don't need the typedef struct SerialNode { ... } SerialNode;, this is a c idiom. In c++, you just write struct SerialNode { ... }; and use SerialNode as a type name.
If you want to prevent a default constructor, make it private as you already do with the assignment operator
class SerialNode {
private:
SerialNode();
SerialNode &operator=(SerialNode&);
...
};
Don't use char* members, use std::string instead. C++ strings are much easier and safer to use than plain char pointers and the associated heap allocation.
Same goes for the map key; if you use std::string as a key, you don't need MapStrComp anymore, because std::string already provides an appropriate comparison.
Probably nicer is to wrap the whole thing in a singleton class:
class Config {
public:
static Config const& get() { return *config; }
static void load();
SerialNode const* operator[](const char*);
private:
static Config* config;
SerialMap map;
};
void Config::load() {
config = new Config();
// put things into it
}
Disclaimer: not tested, and haven't used C++ in a while, so there might be some syntax errors :)

Extending a class and maintaining binary backward compatibility

I'm trying to add new functionality to an existing library. I would need to add new data to a class hierarchy so that the root class would have accessors for it. Anyone should be able to get this data only sub-classes could set it (i.e. public getter and protected setter).
To maintain backward compatibility, I know I must not do any of the following (list only includes actions relevant to my problem):
Add or remove virtual functions
Add or remove member variables
Change type of existing member variable
Change signature of existing function
I can think of two ways to add this data to hierarchy: adding a new member variable to root class or adding pure virtual accessor functions (so that data could be stored in sub-classes). However, to maintain backward compatilibity I can not do either of these.
The library is using extensively pimpl idiom but unfortunately the root class I have to modify does not use this idiom. Sub-classes, however, use this idiom.
Now only solution that I can think of is simulating member variable with static hash-map. So I could create a static hash-map, store this new member to it, and implement static accessors for it. Something like this (in pseudo c++):
class NewData {...};
class BaseClass
{
protected:
static setNewData(BaseClass* instance, NewData* data)
{
m_mapNewData[instance] = data;
}
static NewData* getNewData(BaseClass* instance)
{
return m_mapNewData[instance];
}
private:
static HashMap<BaseClass*, NewData*> m_mapNewData;
};
class DerivedClass : public BaseClass
{
void doSomething()
{
BaseClass::setNewData(this, new NewData());
}
};
class Outside
{
void doActions(BaseClass* action)
{
NewData* data = BaseClass::getNewData(action);
...
}
};
Now, while this solution might work, I find it very ugly (of course I could also add non-static accessor functions but this wouldn't remove the ugliness).
Are there any other solutions?
Thank you.
You could use the decorator pattern. The decorator could expose the new data-elements, and no change to the existing classes would be needed. This works best if clients obtain their objects through factories, because then you can transparently add the decorators.
Finally, check binary compatibility using automated tools like abi-compliance-checker.
You can add exported functions (declspec import/export) without affecting binary compatibility (ensuring you do not remove any current functions and add your new functions at the end), but you cannot increase the size of the class by adding new data members.
The reason you cannot increase the size of the class is that for someone that compiled using the old size but uses the newly extended class would mean that the data member stored after your class in their object (and more if you add more than 1 word) would get trashed by the end of the new class.
e.g.
Old:
class CounterEngine {
public:
__declspec(dllexport) int getTotal();
private:
int iTotal; //4 bytes
};
New:
class CounterEngine {
public:
__declspec(dllexport) int getTotal();
__declspec(dllexport) int getMean();
private:
int iTotal; //4 bytes
int iMean; //4 bytes
};
A client then may have:
class ClientOfCounter {
public:
...
private:
CounterEngine iCounter;
int iBlah;
};
In memory, ClientOfCounter in the old framework will look something like this:
ClientOfCounter: iCounter[offset 0],
iBlah[offset 4 bytes]
That same code (not recompiled but using your new version would look like this)
ClientOfCounter: iCounter[offset 0],
iBlah[offset 4 bytes]
i.e. it doesn't know that iCounter is now 8 bytes rather than 4 bytes, so iBlah is actually trashed by the last 4 bytes of iCounter.
If you have a spare private data member, you can add a Body class to store any future data members.
class CounterEngine {
public:
__declspec(dllexport) int getTotal();
private:
int iTotal; //4 bytes
void* iSpare; //future
};
class CounterEngineBody {
private:
int iMean; //4 bytes
void* iSpare[4]; //save space for future
};
class CounterEngine {
public:
__declspec(dllexport) int getTotal();
__declspec(dllexport) int getMean() { return iBody->iMean; }
private:
int iTotal; //4 bytes
CounterEngineBody* iBody; //now used to extend class with 'body' object
};
If your library is open-source then you can request to add it to the upstream-tracker. It will automatically check all library releases for backward compatibility. So you can easily maintain your API.
EDIT: reports for qt4 library are here.
It is hard to maintain binary compatibility - it is much easier to maintain only interface compatibility.
I think that the only reasonable solution is to break supporting current library and redesign it to only export pure virtual interfaces for classes.
That interfaces could never be modified in the future, but you can add new interfaces.
In that interfaces you could only use primitive types like pointers and specified size integers or floats. You should not have interfaces with for example std::strings or other non-primitive types.
When returning pointers to data allocated in DLL, you need to provide a virtual method for deallocation, so that the application deallocates the data using DLL's delete.
Adding data members to the root will break binary compatibility (and force a rebuild, if that is your concern), but it won't break backward compatibility and neither will adding member functions (virtual or not). Adding new member functions is the obvious way to go.