Dear reader, Hereby I supply a patch for protobuf-2.4.1 which implements the ability to use const method callbacks.
Kind regards, Ralph Langendam Op donderdag 13 september 2012 14:37:03 UTC+2 schreef Ralph het volgende: > > Dear reader, > > It has come to my attention that the callback mechanism of protobuf 2.4.1 > doesn't support the usage of const class methods, as the following example > demonstrates: > > class C {public: > Closure* GetClosure () const { > return NewCallback<C> (this, &C::RunCallback); > } > > void RunCallback () const { > } > }; > > I propose the solution in the attachment for all method callbacks. I've only > made an implementation for MethodClosure0, but the others are pretty similar. > > Kind regards, > > Ralph Langendam > > > -- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To view this discussion on the web visit https://groups.google.com/d/msg/protobuf/-/Is-cee-y_8MJ. To post to this group, send email to protobuf@googlegroups.com. To unsubscribe from this group, send email to protobuf+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.
diff -u -r protobuf-2.4.1.orig/src/google/protobuf/compiler/cpp/cpp_service.cc protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_service.cc --- protobuf-2.4.1.orig/src/google/protobuf/compiler/cpp/cpp_service.cc 2012-04-06 10:32:09.000000000 +0200 +++ protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_service.cc 2012-09-19 11:29:19.000000000 +0200 @@ -89,7 +89,7 @@ "\n" "// implements Service ----------------------------------------------\n" "\n" - "const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n" + "const ::google::protobuf::ServiceDescriptor* GetDescriptor() const;\n" "void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n" " ::google::protobuf::RpcController* controller,\n" " const ::google::protobuf::Message* request,\n" @@ -180,7 +180,7 @@ " return $classname$_descriptor_;\n" "}\n" "\n" - "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n" + "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() const {\n" " protobuf_AssignDescriptorsOnce();\n" " return $classname$_descriptor_;\n" "}\n" diff -u -r protobuf-2.4.1.orig/src/google/protobuf/service.h protobuf-2.4.1/src/google/protobuf/service.h --- protobuf-2.4.1.orig/src/google/protobuf/service.h 2012-04-06 10:32:11.000000000 +0200 +++ protobuf-2.4.1/src/google/protobuf/service.h 2012-09-18 09:28:55.000000000 +0200 @@ -136,7 +136,7 @@ }; // Get the ServiceDescriptor describing this service and its methods. - virtual const ServiceDescriptor* GetDescriptor() = 0; + virtual const ServiceDescriptor* GetDescriptor() const = 0; // Call a method of the service specified by MethodDescriptor. This is // normally implemented as a simple switch() that calls the standard diff -u -r protobuf-2.4.1.orig/src/google/protobuf/stubs/common.h protobuf-2.4.1/src/google/protobuf/stubs/common.h --- protobuf-2.4.1.orig/src/google/protobuf/stubs/common.h 2012-04-06 10:32:13.000000000 +0200 +++ protobuf-2.4.1/src/google/protobuf/stubs/common.h 2012-09-19 11:29:19.000000000 +0200 @@ -865,20 +865,30 @@ class MethodClosure0 : public Closure { public: typedef void (Class::*MethodType)(); + typedef void (Class::*CMethodType)() const; MethodClosure0(Class* object, MethodType method, bool self_deleting) - : object_(object), method_(method), self_deleting_(self_deleting) {} + : object_(object), cobject_(0), method_(method), cmethod_(0), self_deleting_(self_deleting) {} + MethodClosure0(const Class* object, CMethodType cmethod, bool self_deleting) + : object_(0), cobject_(object), method_(0), cmethod_(cmethod), self_deleting_(self_deleting) {} ~MethodClosure0() {} void Run() { bool needs_delete = self_deleting_; // read in case callback deletes - (object_->*method_)(); + if (object_) { + (object_->*method_)(); + } + else { // cobject_ + (cobject_->*cmethod_)(); + } if (needs_delete) delete this; } private: Class* object_; + const Class* cobject_; MethodType method_; + CMethodType cmethod_; bool self_deleting_; }; @@ -998,10 +1008,22 @@ // See Closure. template <typename Class> +inline Closure* NewCallback(const Class* object, void (Class::*method)() const) { + return new internal::MethodClosure0<Class>(object, method, true); +} + +// See Closure. +template <typename Class> inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) { return new internal::MethodClosure0<Class>(object, method, false); } +// See Closure. +template <typename Class> +inline Closure* NewPermanentCallback(const Class* object, void (Class::*method)() const) { + return new internal::MethodClosure0<Class>(object, method, false); +} + // See Closure. template <typename Arg1> inline Closure* NewCallback(void (*function)(Arg1), Only in protobuf-2.4.1/vsprojects: libprotobuf.vcxproj Only in protobuf-2.4.1/vsprojects: libprotobuf.vcxproj.filters