So I've read Developing C wrapper API for Object-Oriented C++ code and I like the approach, which I have taken with my library - opaque handles for each corresponding C++ class; avoiding using void*
But now, I'm faced with thinking about 'interfaces', and base classes. For example, I have a class hierarchy of "channel" classes - a base class for a "channel" and derived concrete classes for, for example, serial comms, in-memory buffers, sockets, etc.
So I have:
typedef struct serial_channel serial_channel;
typedef struct socket_channel socket_channel;
typedef struct memory_channel memory_channel;
serial_channel* create_serial_channel();
socket_channel* create_socket_channel();
memory_channel* create_memory_channel();
But I want to be able to pass any one of those into a function to associate it with a 'device' object:
void associate_device_with_channel(device*, channel*);
Easy in C++, since it understands base classes. How do I approach this in the C wrapper library - what type is channel in C?
The only thing I can think of is that I must resort to void* to represent a base class?
typedef void* channel;
void associate_device_with_channel(device*, channel*);
It works, but would let me pass any pointer?
On the other extreme, I can write a set of functions matching the derived channel classes:
void associate_device_with_serial_channel(device*, serial_channel*);
void associate_device_with_socket_channel(device*, socket_channel*);
void associate_device_with_memory_channel(device*, memory_channel*);
It's very verbose, and if I have to add new channel types, I have to add new functions to the interface as well.
Is there some kind of middle ground I've been missing? - like a single function, but not void*?
There isn't any perfect approach. You're trying to make your function take some opaque handles (the ones with the appropriate base class) but not any handle type (which void* would accept), and there just isn't a thing in C for that.
If you like, you can provide a function which takes serial_channel* and returns channel*, and another one for each other channel subclass. This gets you away from unsafe C casting, and doesn't require numfuncs*numderivedclasses different channel-taking functions.
Personally, I'd just void* it. They're using C, after all... clearly they don't care too much about their language keeping them safe.
First, I would set up my structures something like this:
typedef void base_class;
struct base_class_impl
{
// base class member variables go here
}
struct derived_class
{
// base class must come first in the derived struct
struct base_class_impl base;
// derived class member variables go here
}
Then, I would take pointers to base_class as arguments to my functions:
int base_class_get_count(base_class *b);
and I would always cast at the start of the function:
int base_class_get_count(base_class *b)
{
struct base_class *base = (struct base_class *)b;
// Operate on the object now
}
This enables base_class_get_count() to work even on objects of the derived type. The downside is that it doesn't allow the derived type to override a method - you would have to go a step further, implementing your own table of function pointers which the API calls (like base_class_get_count) dispatch out to, based on the entry in the table.
If you only target GCC or Clang (I suspect that you wouldn't bother with C if you were targeting Visual Studio), one of your options is to create a union with the non-standard __transparent_union__ attribute to list the types that a function can accept. A function accepting a union parameter with the __transparent_union__ attribute will accept either that union, or any type contained in it.
union associable_channel
{
channel* a;
serial_channel* b;
socket_channel* c;
memory_channel* d;
} __attribute__((__transparent_union__));
void associate_device_with_channel(union associable_channel chan);
serial_channel* serial;
socket_channel* socket;
memory_channel* mem;
associate_device_with_channel(serial);
associate_device_with_channel(socket);
associate_device_with_channel(mem);
Related
Function1 can be called with any type T which will be converted to (void*) to be able to add to the list but with this I lose the original pointer type (I need t store tham in one linkedlist because I cannot create one for every possible type). So somehow I need to save the type of the pointer as well. I know that it cant be done using c++. Can anyone suggest an alternative solution?
class MyClass
{
template<class T>
void function1(T* arg1)
{
myList.add((void*)arg);
}
void function2()
{
for(int i = 0; i < myList.size(); i++)
{
myList.get(i);
//restore the original pointer type
}
}
STLinkedlist<void*> myList;
}
The usual way to handle these kinds of problems is by using a public interface, in C++ this is done through inheritance. This can be a drag, especially in constrained situations, where a full class/interface hierarchy would provide too much code/runtime overhead.
In comes Boost.Variant, which allows you to use the same object to store different types. If you need even more freedom, use Boost.Any. For a comparison, see e.g. here.
At the end of the day (or better: rather sooner than later), I'd try to do things differently so you don't have this problem. It may well be worth it in the end.
If you lost the type info by going void* it is just gone. You can not just restore it.
So you either must store extra information along with the pointer, then use branching code to cast it back, or rather drive design to avoid the loss.
Your case is pretty suspicious that you do not what you really want.
A more usual case is that you want a polymorphic collection. That doesn't store any kind of pointers but those belonging to the same hierarchy. Collection has Base* pointers, and you can use the objects through Base's interface, all calling the proper virtual function without programmer's interaction. And if you really need to cast to the original type you can do it via dynamic_cast safely. Or add some type info support in the base interface.
Function1 can be called with any type T which will be converted to (void*) to be able to add to the list but with this I lose the original pointer type (I need t store tham in one linkedlist because I cannot create one for every possible type).
You're having the XY problem. The solution is not to decay your pointers to void* and store type information.
You simply can create a type for every possible type - you create a template type. You need to define an abstract interface for your "type for every object", then define a template class implementing this interface, that is particularized by type. Finally, you create your custom-type instance on your type of pointer received and store them by base class pointer (where the base class is your interface definition).
All that said, you (normally) shouldn't need to implement this at all, because the functionality is already implemented in boost::any or boost::variant (you will have to choose one of them).
General
Take into consideration, that if you want to store different objects inside a std::vector<void *>, mostly likely your application has a bad design. In this case, I'd think, whether it is really necessary to do it (or how can it be done in another way), rather than searching for the solution, how to do it.
However, there are no fully evil things in C++ (nor in any other language), so if you are absolutely certain, that this is the only solution, here are three possible ways to solve your problem.
Option 1
If you store only pointers to simple types, store the original type along with the pointer by an enum value or simply a string.
enum DataType
{
intType,
floatType,
doubleType
};
std::vector<std::pair<void *, DataType>> myData;
Option 2
If you store mixed data (classes and simple types), wrap your data in some kind of class.
class BaseData
{
public:
virtual ~BaseData() { }
};
class IntData : public BaseData
{
public:
int myData;
};
std::vector<BaseData *> myData;
Later, you'll be able to check the type of your data using dynamic_cast.
Option 3
If you store only classes, store them simply as a pointer to their base class and dynamic_cast your way out.
You could use boost::any to store any type in your list instead of use void*. It's not exactly what you want but I don't think you can restore the type in run time (as Kerrek said, it's not Java).
class MyClass
{
template<class T>
void function1(T arg1)
{
myList.add(arg);
}
template<class T>
T get(int i)
{
return boost::any_cast<T>(myList.get(i));
}
STLinkedlist<boost::any> myList;
};
Given:
Object of class A contains an array of objects.
Each of these objects must implement some interface IB, because A use methods of IB.
These objects are passed to object of class A by client, and they are of type C or its children. A must return these objects back to clients.
Problem: A must not know anything about C, only about IB, but A must return C.
Is there any standard solution in C++ without unsafe casts<>?
I don't think this is possible with A not knowing anything about C. However, having A know enough to use the right interface is not that hard in C++. Have all classes with IB derive from a single abstract base class with the interface defined there as pure virtual functions. This actually corresponds to proper C++ design--separating interface from implementation--as described in e.g. Sutter & Alexandrescu.
Otherwise, if the above really is impossible, you could make A a template class, and store the array elements as void*, resolving the class type (at compile time) using static_cast.
You could implement a perfectly safe class using templates.
template <typename T>class A
{
std::vector<IB*> myObj;
public:
void add(IB* anObj)
{
myObj.push_back(anObj);
}
void get(int anIndex, T*& anObj)
{
T* t = dynamic_cast<T*>(myObj[anIndex]);
anObj = t;
}
};
And then use like this.
A<C> a;
Demo is given here
I have this problem again and again... and still have not a satisfactory answer...
Especially when I put the class into a container, later on I need to record more information on every element in the container during a specific processing, but after processing I do not need the extra information anymore....
I often found some libraries try to solve the above situation by defining a void* in their data structure to provide user-defined data structure extension. Just the same described in this Q&A.
But it produces memory / resource handling problem... and other problems that I feel this approach is error-prone.
In the modern day of object-oriented programming, I am thinking of
using inheritance & polymorphism. Use base class's pointer in the container, but then I have to add derived class's accessor into the base class. It is kind of strange...
is there any other better ways to extend a class's property while maintain container comparability in C++?
The best way to store extra data about a object without actually compromising the integrity of the object itself is to store a pair of data in the container instead.
struct User { ... };
struct ExtraData { ... };
typedef std::pair<User, ExtraData> UserAndExtraData;
Now I can create a container type in C++ which stores both pieces of information together without compromising the independence of either type.
std::vector<UserAndExtraData> vector;
I would look into the Decorator Pattern. You can decorate your objects while processing them then throw the decorated objects away. If there is a lot of shared data you can also look into the FlyWeight pattern.
"User" could be extended by template parameters. for example,
template <typename... Extra>
struct User : Extra...
{
...
};
struct ExtraData {...};
struct ExtraExtraData {...};
using ExtraUser = User<ExtraData>;
using MoreExtraUser = User<ExtraData, ExtraExtraData>;
In the modern day of object-oriented programming, I am thinking of
using inheritance & polymorphism. Use base class's pointer in the
container, but then I have to add derived class's accessor into the
base class. It is kind of stange...
you don't need to put a pointer to your derived class in your base class when using inheritance. You just need to cast to the derived class. the problem is getting your data into the derived objects when it's stored in the base objects - you can only cast them if they were created as the derived type, even if your collection holds them as the base type. (if they are created as the derived type, then just cast!)
So if you have a collection of BaseC, you can create a new class DerivedC that has a copy constructor that takes a BaseC. You can copy your BaseC object into it, perform your processing on the DerivedC objects and then copy these back into a BaseC object for storage. This uses the Flyweight pattern. Note that if you have a collection of BaseC objects, you cannot just pretend they are DerivedC classes as they will not have the storage to hold all the data members, you need to create new DerivedC objects.
Alternatively, create a new class just for processing that contains a (smart pointer) reference to your base class objects, copy the reference in, perform the processing, delete the processing objects when you're done.
If your objects are in a vector, then a simple approach is to make a parallel vector:
void doSomething(const vector<MyObject>& my_objects)
{
vector<ExtraData> extra_data;
int n_objects = extra_data.size();
extra_data.reserve(n_objects);
for (int i=0; i!=n_objects; ++i) {
extra_data.push_back(calcExtraData(my_objects[i]));
}
// now use my_objects[i] and extra_data[i] together.
// extra data goes away when the function returns.
}
You don't have to modify your original objects, and it is very efficient.
If you have some other container type, you can use a map:
void doSomething(const set<MyObject>& my_objects)
{
map<MyObject*,ExtraData> extra_data;
set<MyObject>::const_iterator i=my_objects.begin(), end=my_objects.end();
for (;i!=end;++i) {
extra_data[&*i] = calcExtraData(*i);
}
// now use extra_data[&obj] to access the extra data for obj.
// extra data goes away when the function returns.
}
this isn't as efficient as with vectors, but you still don't have to modify your original classes.
However, it becomes more difficult to maintain the parallel structures if the underlying container can change during the processing.
One simple option is to add a type parameter representing the "extra data"...
template<class ExtraDataType>
struct MyExtensibleContainer
{
...
ExtraDataType extra;
};
Perhaps if you indicate why this solution isn't sufficient, the true requirements will come through.
Example for int and void*:
struct IntOrVoid
{
};
struct IntOrVoid1 : IntOrVoid
{
int x;
};
struct IntOrVoid2 : IntOrVoid
{
void* x;
};
typedef shared_ptr<IntOrVoid> PIntOrVoid;
then use MyExtensibleContainer<PIntOrVoid>
or altenatively:
union IntOrVoid
{
int x_int;
void* x_voidp;
};
then use MyExtensibleContainer<IntOrVoid>
The problem you are describing has nothing to do with adding an "extra" data type. The problem you are describing has to do with holding a variant type that can have one of many hetrogeneous types. There are many ways to do this, it is a much more general problem.
I've been programming in Java way too long, and finding my way back to some C++. I want to write some code that given a class (either a type_info, or its name in a string) can create an instance of that class. For simplicity, let's assume it only needs to call the default constructor. Is this even possible in C++, and if not is it coming in a future TR?
I have found a way to do this, but I'm hoping there is something more "dynamic". For the classes I expect to wish to instantiate (this is a problem in itself, as I want to leave that decision up to configuration), I have created a singleton factory with a statically-created instance that registers itself with another class. eg. for the class Foo, there is also a FooFactory that has a static FooFactory instance, so that at program startup the FooFactory constructor gets called, which registers itself with another class. Then, when I wish to create a Foo at runtime, I find the FooFactory and call it to create the Foo instance. Is there anything better for doing this in C++? I'm guessing I've just been spoiled by rich reflection in Java/C#.
For context, I'm trying to apply some of the IOC container concepts I've become so used to in the Java world to C++, and hoping I can make it as dynamic as possible, without needing to add a Factory class for every other class in my application.
You could always use templates, though I'm not sure that this is what your looking for:
template <typename T>
T
instantiate ()
{
return T ();
}
Or on a class:
template <typename T>
class MyClass
{
...
};
Welcome in C++ :)
You are correct that you will need a Factory to create those objects, however you might not need one Factory per file.
The typical way of going at it is having all instanciable classes derive from a common base class, that we will call Base, so that you'll need a single Factory which will serve a std::unique_ptr<Base> to you each time.
There are 2 ways to implement the Factory:
You can use the Prototype pattern, and register an instance of the class to create, on which a clone function will be called.
You can register a pointer to function or a functor (or std::function<Base*()> in C++0x)
Of course the difficulty is to register those entries dynamically. This is typically done at start-up during static initialization.
// OO-way
class Derived: public Base
{
public:
virtual Derived* clone() const { return new Derived(*this); }
private:
};
// start-up...
namespace { Base* derived = GetFactory().register("Derived", new Derived); }
// ...or in main
int main(int argc, char* argv[])
{
GetFactory().register("Derived", new Derived(argv[1]));
}
// Pointer to function
class Derived: public Base {};
// C++03
namespace {
Base* makeDerived() { return new Derived; }
Base* derived = GetFactory().register("Derived", makeDerived);
}
// C++0x
namespace {
Base* derived = GetFactory().register("Derived", []() { return new Derived; });
}
The main advantage of the start-up way is that you can perfectly define your Derived class in its own file, tuck the registration there, and no other file is impacted by your changes. This is great for handling dependencies.
On the other hand, if the prototype you wish to create requires some external information / parameters, then you are forced to use an initialization method, the simplest of which being to register your instance in main (or equivalent) once you have the necessary parameters.
Quick note: the pointer to function method is the most economic (in memory) and the fastest (in execution), but the syntax is weird...
Regarding the follow-up questions.
Yes it is possible to pass a type to a function, though perhaps not directly:
if the type in question is known at compile time, you can use the templates, though you'll need some time to get acquainted with the syntax
if not, then you'll need to pass some kind of ID and use the factory approach
If you need to pass something akin to object.class then it seems to me that you are approaching the double dispatch use case and it would be worth looking at the Visitor pattern.
No. There is no way to get from a type's name to the actual type; rich reflection is pretty cool, but there's almost always a better way.
no such thing as "var" or "dynamic" in C++ last time I've checked(although that was a WHILE ago). You could use a (void*) pointer and then try casting accordingly. Also, if memory serves me right, C++ does have RTTI which is not reflection but can help with identifying types at runtime.
I read that early C++ "compilers" actually translated the C++ code to C and used a C compiler on the backend, and that made me wonder. I've got enough technical knowledge to wrap my head around most of how that would work, but I can't figure out how to do class inheritance without having language support for it.
Specifically, how do you define a class with a few fields, then a bunch of subclasses that inherit from it and each add their own new fields, and be able to pass them around interchangeably as function arguments? And especially how can you do it when C++ allows you to allocate objects on the stack, so you might not even have pointers to hide behind?
NOTE: The first couple answers I got were about polymorphism. I know all about polymorphism and virtual methods. I've even given a conference presentation once about the low-level details of how the virtual method table in Delphi works. What I'm wondering about is class inheritance and fields, not polymorphism.
In C anyway you an do it the way cfront used to do it in the early days of C++ when the C++ code was translated into C. But you need to be quite disciplined and do all the grunt work manually.
Your 'classes' have to be initialized using a function that performs the constructor's work. this will include initializing a pointer to a table of polymorphic function pointers for the virtual functions. Virtual function calls have to be made through the vtbl function pointer (which will point to a structure of function pointers - one for each virtual function).
The virtual function structure for each derived calss needs to be a super-set of the one for the base class.
Some of the mechanics of this might be hidden/aided using macros.
Miro Samek's first edition of "Practical Statecharts in C/C++" has an Appendix A - "C+ - Object Oriented Programming in C" that has such macros. It looks like this was dropped from the second edition. Probably because it's more trouble than it's worth. Just use C++ if you want to do this...
You should also read Lippman's "Inside the C++ Object Model" which goes into gory details about how C++ works behind the scenes, often with snippets of how things might work in C.
I think I see what you're after. Maybe.
How can something like this work:
typedef
struct foo {
int a;
} foo;
void doSomething( foo f); // note: f is passed by value
typedef
struct bar {
foo base;
int b;
} bar;
int main() {
bar b = { { 1 }, 2};
doSomething( b); // how can the compiler know to 'slice' b
// down to a foo?
return 0;
}
Well you can't do that as simply as that without language support - you'd need to do some things manually (that's what it means to not have language support):
doSomething( b.base); // this works
Basically, structs-within-structs.
struct Base {
int blah;
};
struct Derived {
struct Base __base;
int foo;
};
When you want to, say, cast a Derived * to Base *, you'd actually return a pointer to the __base element of the Derived struct, which in this case is the first thing in the struct so the pointers should be the same (wouldn't be the case for multiple-inherited classes though).
If you want to access blah in this case, you would do something like derived.__base.blah.
Virtual functions are normally done with a special table of function pointers that is part of each object, a rudimentary sort of "what is my type" record.
Here is how COM does it for C language. I am a bit rusty at this , but the essence works like this. Each "class" member variables is just a struct.
struct Shape
{
int value;
};
struct Square
{
struct Shape shape; // make sure this is on top, if not KABOOM
int someothervalue;
};
all the methods, are actually just normal functions. like this
void Draw(Shape * shape,int x,int y)
{
shape->value=10; // this should work even if you put in a square. i think...
}
then, they use the preprocessor to "trick" the C code into displaying something like this.
Square * square;
square->Draw(0,0); // this doesnt make sense, the preprocessor changes it to Draw(square,0,0);
Alas, i dont know what kind of preprocessor tricks are done to make the C++ looking function call resolve into a plan vanilla C call.
DirectX COM objects are declared this way.
Dr. Dobb's had a moderately detailed article on this topic, Single Inheritance Classes in C.
Structs-within-structs is common, but it makes it a pain to access inherited fields. You either need to use indirection (e.g. child->parent.field), or casting (((PARENT *) child)->field).
An alternative I have seen is more like this:
#define COUNTRY_FIELDS \
char *name; \
int population;
typedef struct COUNTRY
{
COUNTRY_FIELDS
} COUNTRY;
#define PRINCIPALITY_FIELDS \
COUNTRY_FIELDS \
char *prince;
typedef struct PRINCIPALITY
{
PRINCIPALITY_FIELDS
} PRINCIPALITY;
This gives types with direct access to inherited fields. The resulting objects can still be safely cast to the parent type, because the parent's fields and the inherited fields start at the same place.
The syntax can be improved a little with macros. I saw this in the older POV-Ray source (but I think they've since converted to C++).
If you want a good reference on how this stuff works take a look at the glib/gdk/gtk open source libraries. They have pretty good documentation and the entire framework is based on C OO.
You can simulate an object by writing constructors, setters, getters, and destructors with the hidden this pointer called out explicitly.
Inheritance is handled by having the derived object include a pointer to the base object in the structure of the derived object.