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

Reply via email to