#include #include #include // This represents a classic-C-style callback API that you can't modify. (If // you CAN modify old callback code, use a boost::function parameter!) void dumb_old_function(void (*callback)(void*), void* data) { std::cout << "About to call callback()\n"; callback(data); std::cout << "Back from callback\n"; } // This is your object containing the useful_method() you want to invoke from // dumb_old_function(). class WellDesignedObject { public: WellDesignedObject(const std::string& init): memberdata(init) {} void useful_method() { std::cout << "WellDesignedObject('" << memberdata << "').useful_method()\n"; } void method_with_param(const std::string& param) { std::cout << "WellDesignedObject('" << memberdata << "').method_with_param('" << param << "')\n"; } // The trick is to use a static adapter method that accepts a // WellDesignedObject* as its data pointer. static void static_useful_method_adapter(void* data) { std::cout << "static_useful_method_adapter()\n"; // This is the risky part. If you pass a pointer to some other kind of // data, or if your WellDesignedObject has vanished before we get here // -- Bad Things Happen. WellDesignedObject* self = static_cast(data); self->useful_method(); std::cout << "Back from useful_method()\n"; } private: std::string memberdata; }; void use_adapter() { WellDesignedObject* obj = new WellDesignedObject("abc"); std::cout << "About to call dumb_old_function()\n"; dumb_old_function(&WellDesignedObject::static_useful_method_adapter, obj); std::cout << "Back from dumb_old_function()\n"; delete obj; } // The trouble with the above is that it supports exactly one method in one // class. It doesn't scale well to other methods in the same class, never mind // other classes. A more general tactic is to pass a boost::function as the // opaque data pointer -- then you can bind any callable you can express in // modern C++. typedef boost::function NullaryFunction; void nullary_function_adapter(void* data) { NullaryFunction* function = static_cast(data); (*function)(); } void heap_function_object() { WellDesignedObject* obj = new WellDesignedObject("def"); NullaryFunction* func = new NullaryFunction(boost::bind(&WellDesignedObject::useful_method, obj)); std::cout << "About to call dumb_old_function()\n"; dumb_old_function(&nullary_function_adapter, func); std::cout << "Back from dumb_old_function()\n"; // But wait! you say. NullaryFunction is too restrictive! What if I need // to pass arbitrary data to my callback? NullaryFunction* func2 = new NullaryFunction(boost::bind(&WellDesignedObject::method_with_param, obj, "arbitrary")); std::cout << "About to call dumb_old_function() again\n"; dumb_old_function(&nullary_function_adapter, func2); std::cout << "Back from dumb_old_function() again\n"; delete func2; delete func; delete obj; } int main(int argc, char *argv[]) { use_adapter(); std::cout << "\n"; heap_function_object(); return 0; }