views:

655

answers:

9

I'm implementing a CORBA like server. Each class has remotely callable methods and a dispatch method with two possible input, a string identifying the method or an integer which would be the index of the method in a table. A mapping of the string to the corresponding integer would be implemented by a map.

The caller would send the string on the first call and get back the integer with the response so that it simply has to send the integer on subsequent calls. It is just a small optimization. The integer may be assigned dynamically on demand by the server object. The server class may be derived from another class with overridden virtual methods.

What could be a simple and general way to define the method binding and the dispatch method ?

Edit: The methods have all the same signature (no overloading). The methods have no parameters and return a boolean. They may be static, virtual or not, overriding a base class method or not. The binding must correctly handle method overriding.

The string is class hierarchy bound. If we have A::foo() identified by the string "A.foo", and a class B inherits A and override the method A::foo(), it will still be identified as "A.foo", but the dispatcher will call A::foo if the server is an A object and B::foo if it is a B object.

Edit (6 apr): In other words, I need to implement my own virtual method table (vftable) with a dynamic dispatch method using a string key to identify the method to call. The vftable should be shared among objects of the same class and behave as expected for polymorphism (inherited method override).

Edit (28 apr): See my own answer below and the edit at the end.

A: 

It looks like you're looking for something like reflection or delegates -- I'm not 100% sure what you're trying to accomplish, but it seems the best way of doing that is just having a map of function pointers:

typedef size_t (*CommonMethodPointerType)(const unsigned char *);
std::map<std::string, CommonMethodPointerType> functionMapping;

size_t myFunc(const std::string& functionName, const unsigned char * argument) {
    std::map<std::string, CommonMethodPointerType>::iterator functionPtrIterator
        = functionMapping.find(functionName);
    if (FunctionPtrIterator == functionMapping.end())
        return ERROR_CODE;
    return (*functionPtrIterator)(argument);
}

You could implement some form of optimization similar to your integer by returning the iterator to the client so long as you know the mapping will not change.

If you're looking for "dynamic binding" like that allowed in C# or dynamic languages like PHP, unfortunately you really can't do that -- C++ destroys type information when code is compiled.

Hope that helps!

Billy ONeal
This solution I knew and works for function. I need it for methods and overridden virtual methods. The methods have all the same parameters, so the binding is performed only on the string.
chmike
@chmike: Then just create a pointer to the member function. You can use `std::mem_fun` to make your pointer-to-member behave like a normal functor, and you can then make your map contain `std::unary_function` s instead, or a similar functor. The pattern doesn't need to change just because you want to use member functions.
Billy ONeal
EDIT: Example syntax on pointer-to-member-functions here: http://www.goingware.com/tips/member-pointers.html#not-addresses
Billy ONeal
The function binding map must be able to contain methods of different classes (derived) and the correct method must be called. The solution you propose won't match this requirement. The solution I found so far is to define an abstract base class with a virtual method, then a derived template class where the overriding method calls the class T::method(). The map is defined to contain abstract base classes. This solves the polymorphism constrain. I guess there is no better solution for this.
chmike
@chmike: `std::unary_function` is that one base class that goes in the map.
Billy ONeal
What I have described is Functionoid by using a template class. The class is then automatically defined. See [http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10]. unary_function doesn't match the requirement.
chmike
I don't see why. `std::mem_fun` returns a `std::unary_function` you can store in the map. So long as all the functions accept the same type of parameter and return the same type of parameter, I fail to see how it doesn't match the requirement. But then again, I had difficulty understanding your requirement in the first place.
Billy ONeal
Could you give some example how the map is defined and how I add a method pointer in the map and how I would call it ?
chmike
@chmike: Spent some time rereading what you wrote above a few times -- "the class is automaticly defined" -- no, you cant do that. You'd have to pass a pointer to the instance of the class. If you need that, just create a function which instantiates the class and calls the pointer, and put that in your map.
Billy ONeal
A: 

You might like to rephrase the question slightly as static and dynamic binding actually have a specific meaning in C++.

For example, default values for parameters are determined at compile time so if I have a virtual method in a base class that declares default values for its parameters then those values are set at compile time.

Any new default values for these parameters that are declared in a derived class will be ignored at run time with the result being that the default parameter values in the base class will be used, even though you called the member function in the derived class.

The default parameter values are said to be statically bound.

Scott Meyers discusses this in an item in his excellent book "Effective C++".

HTH

Rob Wells
The phrasing is correct. Dynamic binding means identifying the method to call at run time. Parameter types are not in play here, all methods have the same parameters. The method gets the message as argument and extract the arguments from it it self. The binding maps a string identifying the method to the method to call.
chmike
Shouldn't that be Scott Meyers?
laginimaineb
@laginimaineb: Yes. Fixed.
Billy ONeal
Oops. Sorry Scott. Thanks @laginimaineb for the heads up and @Billy for the fix.@chmike I think you actually mean dynamic linking rather than dynamic binding.
Rob Wells
+1  A: 

Have you considered using a combination of boost::bind and boost::function? Between these two utilities you can easily wrap any C++ callable in a function object, easily store them in containers, and generally expect it all to "just work". As an example, the following code sample works exactly the way you would expect.

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
using namespace std;

struct A            { virtual void hello() { cout << "Hello from A!" << endl; } };
struct B : public A { virtual void hello() { cout << "Hello from B!" << endl; } };

int main( int argc, char * argv[] )
{
    A a;
    B b;
    boost::function< void () > f1 = boost::bind( &A::hello, a );
    boost::function< void () > f2 = boost::bind( &A::hello, b );
    f1();  // prints: "Hello from A!"
    f2();  // prints: "Hello from B!"
    return 0;
}
Rakis
Boost function pointers are very powerful, but I prefer avoiding a dependency with boost for now.
chmike
A: 

Here is an example of my actual method. It Just Works (c) but I'm pretty sure a much cleaner and better way exist. It compiles and runs with g++ 4.4.2 as is. Removing the instruction in the constructor would be great, but I couldn't find a way to achieve this. The Dispatcher class is basically a dispatchable method table and each instance must have a pointer on its table.

Note: This code will implicitly make all dispatched methods virtual.

#include <iostream>
#include <map>
#include <stdexcept>
#include <cassert>

// Forward declaration
class Dispatchable;

//! Abstract base class for method dispatcher class
class DispatcherAbs
{
public:
    //! Dispatch method with given name on object
    virtual void dispatch( Dispatchable *obj, const char *methodName ) = 0;

    virtual ~DispatcherAbs() {}
};

//! Base class of a class with dispatchable methods
class Dispatchable
{
public:
    virtual ~Dispatchable() {}

    //! Dispatch the call
    void dispatch( const char *methodName )
    {
        // Requires a dispatcher singleton assigned in derived class constructor
        assert( m_dispatcher != NULL );
        m_dispatcher->dispatch( this, methodName );
    }

protected:
    DispatcherAbs *m_dispatcher; //!< Pointer on method dispatcher singleton
};

//! Class type specific method dispatcher
template <class T>
class Dispatcher : public DispatcherAbs
{
public:
    //! Define a the dispatchable method type
    typedef void (T::*Method)();

    //! Get dispatcher singleton for class of type T
    static Dispatcher *singleton()
    {
        static Dispatcher<T> vmtbl;
        return &vmtbl;
    }

    //! Add a method binding
    void add( const char* methodName, Method method )
        { m_map[methodName] = method; }

    //! Dispatch method with given name on object
    void dispatch( Dispatchable *obj, const char *methodName )
    {
        T* tObj = dynamic_cast<T*>(obj);
        if( tObj == NULL )
            throw std::runtime_error( "Dispatcher: class mismatch" );
        typename MethodMap::const_iterator it = m_map.find( methodName );
        if( it == m_map.end() )
            throw std::runtime_error( "Dispatcher: unmatched method name" );
        // call the bound method
        (tObj->*it->second)();
    }

protected:
    //! Protected constructor for the singleton only
    Dispatcher() { T::initDispatcher( this ); }

    //! Define map of dispatchable method
    typedef std::map<const char *, Method> MethodMap;

    MethodMap m_map; //! Dispatch method map
};


//! Example class with dispatchable methods
class A : public Dispatchable
{
public:
    //! Construct my class and set dispatcher
    A() { m_dispatcher = Dispatcher<A>::singleton(); }

    void method1() { std::cout << "A::method1()" << std::endl; }

    virtual void method2() { std::cout << "A::method2()" << std::endl; }

    virtual void method3() { std::cout << "A::method3()" << std::endl; }

    //! Dispatcher initializer called by singleton initializer
    template <class T>
    static void initDispatcher( Dispatcher<T> *dispatcher )
    {
        dispatcher->add( "method1", &T::method1 );
        dispatcher->add( "method2", &T::method2 );
        dispatcher->add( "method3", &T::method3 );
    }
};

//! Example class with dispatchable methods
class B : public A
{
public:
    //! Construct my class and set dispatcher
    B() { m_dispatcher = Dispatcher<B>::singleton(); }

    void method1() { std::cout << "B::method1()" << std::endl; }

    virtual void method2() { std::cout << "B::method2()" << std::endl; }

    //! Dispatcher initializer called by singleton initializer
    template <class T>
    static void initDispatcher( Dispatcher<T> *dispatcher )
    {
        // call parent dispatcher initializer
        A::initDispatcher( dispatcher );
        dispatcher->add( "method1", &T::method1 );
        dispatcher->add( "method2", &T::method2 );
    }
};

int main( int , char *[] )
{
    A *test1 = new A;
    A *test2 = new B;
    B *test3  = new B;

    test1->dispatch( "method1" );
    test1->dispatch( "method2" );
    test1->dispatch( "method3" );

    std::cout << std::endl;

    test2->dispatch( "method1" );
    test2->dispatch( "method2" );
    test2->dispatch( "method3" );

    std::cout << std::endl;

    test3->dispatch( "method1" );
    test3->dispatch( "method2" );
    test3->dispatch( "method3" );

    return 0;
}

Here is the program output

A::method1()
A::method2()
A::method3()

B::method1()
B::method2()
A::method3()

B::method1()
B::method2()
A::method3()

Edit (28 apr): The answers to this related question was enlightening. Using a virtual method with an internal static variable is preferable to using a member pointer variable that needs to be initialized in the constructor.

chmike
Actually the example does not reflect the true usage. In fact the pointer should be declared as a pointer on Dispatchable. This explains why the methods have to be implicitly bound as virtual even if they aren't virtual in fact. The class B, could for instance have a method4 that should be dispatchable.
chmike
A: 

Qt4 has a nice dynamic binding system that's made possible via their "Meta-Object Compiler" (moc). There's a nice writeup on it on their Qt Object Model page.

Simeon Fitch
I'm using Qt already for other projects. Very good software and QtCreator is a great IDE. But this library should be portable (pure C++) and should not depend on thirs party tools.
chmike
A: 

Here is a way do dynamically load classes from shared libraries on Linux http://www.linuxjournal.com/article/3687?page=0,0

There is also a stackoverflow question on this http://stackoverflow.com/questions/496664/c-dynamic-shared-library-on-linux

The same can be done in Windows by dynamically loading C functions from DLLs and then loading those.

The map part is trivial after you have your dynamic loading solution


The really good book Advanced C++ programming idioms and idioms by James O. Coplien has a section on Incremental loading

Romain Hippeau
A: 

I've seen both your example and the answer to the other question. But if you talk about the m_dispatcher member, the situation is very different.

For the original question, there's no way to iterate over methods of a class. You might only remove the repetition in add("method", T::method) by using a macro:

#define ADD(methodname) add(#methodname, T::methodname)

where the '#' will turn methodname into a string like required (expand the macro as needed). In case of similarly named methods, this removes a source of potential typos, hence it is IMHO very desirable.

The only way to list method names IMHO is by parsing output of "nm" (on Linux, or even on Windows through binutils ports) on such files (you can ask it to demangle C++ symbols). If you want to support this, you may want initDispatcher to be defined in a separate source file to be auto-generated. There's no better way than this, and yes, it may be ugly or perfect depending on your constraints. Btw, it also allows to check that authors are not overloading methods. I don't know if it would be possible to filter public methods, however.

I'm answering about the line in the constructor of A and B. I think the problem can be solved with the curiously recurring template pattern, applied on Dispatchable:

template <typename T>
class Dispatchable
{
public:
    virtual ~Dispatchable() {}

    //! Dispatch the call
    void dispatch( const char *methodName )
    {
        dispatcher()->dispatch( this, methodName );
    }
protected:
    static Dispatcher<T> dispatcher() {
        return Dispatcher<T>::singleton();
        //Or otherwise, for extra optimization, using a suggestion from:
        //http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
        static Dispatcher<T>& disp = Dispatcher<T>::singleton();
        return disp;
    }
};

Disclaimer: I couldn't test-compile this (I'm away from a compiler). You may need to forward-declare Dispatcher, but since it gets a template argument I guess argument-dependant lookup makes that unnecessary (I'm not enough of a C++ guru to be sure of this).

I've added a dispatcher() method for convenience, if it is needed elsewhere (otherwise you can inline it in dispatch()).

The reason CRTP is so simple here and so complicated in the other thread is that here your member was not static. I first thought of making it static, then I thought there was no reason for saving the result of the call to singleton() and waste memory, then I looked it up and found this solution. I'm dubious if the extra reference in dispatcher() does save any extra time. In any case, if a m_dispatcher member was needed, it could be initialized in the Dispatchable() constructor.

About your example, since initDispatcher() is a template method, I frankly doubt it is necessary to readd method1 and method2. A::initDispatcher(Dispatcher<B> dispatcher) will correctly add B::method1 to dispatcher.

Blaisorblade
The define macro is excellent. Though in may case, the key is not the method name, so it is not applicable. The idea to use nm and generate the initDispatch outside is very interesting. But this would work only for a very particular context: C++ and unix. Regarding the CRTP, what would happen with derived classes ? They would have to redefine the Dispatchable<T> as base class. The dispatch method should then be virtual. Finally I don't think we gain much in this way. I may have forgot to mention that server class may be extended by inheritance.
chmike
(macro) The example used the method name as key. Your text prepends "A.", and that can be done too. Two consecutive string literals are concated, so you'd need #classname #methodname.(nm) you could make it work on Windows too, either through mingw or through some other specific linker. But yeah, some work.(CRTP) It depends on you. Boost people would write once even more code, to avoid a possibility for a bug, even if it's a trivial bug to fix (you get a crash, see the assertion, read docs, fix it). I'll try to solve it anyway.
Blaisorblade
Even if the dispatch method were virtual, it wouldn't fix the problem you mention, it seems. If B inherits from Dispatchable<B>, it'll get another virtual dispatch method, and it'll get ambiguous.The other solution is to add a template parameter to A to be passed to Dispatchable, so that B extends A<B>. Unfortunately, such a B would not extend A<A>, which sucks.
Blaisorblade
A: 
class Report   //This denotes the base class of C++ virtual function
{ 
public: 
    virtual void create()   //This denotes the C++ virtual function
    { 
        cout <<"Member function of Base Class Report Accessed"<<endl; 
    } 
};

class StudentReport: public Report 
{ 
public: 
    void create() 
    { 
        cout<<"Virtual Member function of Derived class StudentReportAccessed"<<endl; 
    } 
};

void main() 
{
    Report *a, *b; 
    a = new Report(); 
    a->create(); 
    b = new StudentReport(); 
    b->create();     
}
bachchan
A: 

By the way - don't forget that the numeric position of virtual functions dispatched from a vtable correspond identically, with all compilers, to the sequence they appear in the corresponding header file. You may be able to take advantage of that. That is a core principle upon which Microsoft COM technology is based.

Also, you might consider an approach published in "Game Programming Gems" (first volume) by Mark DeLoura. The article is entitled a "generic function binding interface" and is intended for RPC / network binding of functions. It may be exactly what you want.

Brent Arias
Interesting reading but the described method is not portable C++ code.The question was not how to write an RPC system. I have already the parameter marshalling system as well as the method identifier (A world wide unique identifier). The question is how to optimally define the method dispatching table. The vftable property you suggest is not standard C++ and it requires that methods are virtual. The method I already described works with non virtual methods and thus with template methods too (not implicit).
chmike