From c995de65847d8a97dc75294fb1b9b6a057fd3c1d Mon Sep 17 00:00:00 2001 From: KennyTM~ Date: Sun, 13 May 2012 20:49:05 +0800 Subject: [PATCH] Allow the ZMQ_MONITOR code compilable on gcc 4.7 on Linux. The current ZMQ_MONITOR code does not compile in gcc 4.7, as -pedantic and -Werror are enabled, and ISO C++ doesn't allow casting between normal pointers (void*) and function pointers, as pedantically their size could be different. This caused the library not compilable. This commit workaround the problem by introducing one more indirection, i.e. instead of calling (void *)listener which is an error, we have to use *(void **)&listener which is an undefined behavior :) but works on most platforms Also, `optval_ = monitor` will not set the parameter in getsockopt(), and the extra casting caused the LHS to be an rvalue which again makes the code not compilable. The proper way is to pass a pointer of function pointer and assign with indirection, i.e. `*optval_ = monitor`. Also, fixed an asciidoc error in zmq_getsockopt.txt because the `~~~~` is too long. --- doc/zmq_getsockopt.txt | 2 +- src/options.cpp | 6 +++--- src/session_base.cpp | 2 ++ tests/test_monitor.cpp | 15 +++++++++------ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/doc/zmq_getsockopt.txt b/doc/zmq_getsockopt.txt index 3548c39c..e7ccd4a9 100644 --- a/doc/zmq_getsockopt.txt +++ b/doc/zmq_getsockopt.txt @@ -456,7 +456,7 @@ Default value:: -1 (leave to OS default) Applicable socket types:: all, when using TCP transports. ZMQ_MONITOR: Registers a callback for socket state changes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Registers a callback function / event sink for changes in underlying socket state. The default value of `NULL` means no monitor callback function. diff --git a/src/options.cpp b/src/options.cpp index 8fb47a35..d24834c1 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -325,7 +325,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, errno = EINVAL; return -1; } - monitor = ((zmq_monitor_fn*) optval_); + monitor = *((zmq_monitor_fn**) &optval_); return 0; } } @@ -550,8 +550,8 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) errno = EINVAL; return -1; } - ((zmq_monitor_fn*) optval_) = monitor; - *optvallen_ = sizeof (void *); + *((zmq_monitor_fn**) &optval_) = monitor; + *optvallen_ = sizeof (zmq_monitor_fn*); return 0; } diff --git a/src/session_base.cpp b/src/session_base.cpp index 2ada9707..681b1455 100644 --- a/src/session_base.cpp +++ b/src/session_base.cpp @@ -20,6 +20,8 @@ along with this program. If not, see . */ +#include + #include "session_base.hpp" #include "socket_base.hpp" #include "i_engine.hpp" diff --git a/tests/test_monitor.cpp b/tests/test_monitor.cpp index 6822803d..28197e15 100644 --- a/tests/test_monitor.cpp +++ b/tests/test_monitor.cpp @@ -99,16 +99,18 @@ int main (int argc, char *argv []) assert (rep); // Expects failure - invalid size - rc = zmq_setsockopt (rep, ZMQ_MONITOR, (void *)listening_sock_monitor, 20); + zmq_monitor_fn *monitor; + monitor = listening_sock_monitor; + + rc = zmq_setsockopt (rep, ZMQ_MONITOR, *(void **)&monitor, 20); assert (rc == -1); assert (errno == EINVAL); - rc = zmq_setsockopt (rep, ZMQ_MONITOR, (void *)listening_sock_monitor, sizeof (void *)); + rc = zmq_setsockopt (rep, ZMQ_MONITOR, *(void **)&monitor, sizeof (void *)); assert (rc == 0); - void *monitor; size_t sz = sizeof (void *); - rc = zmq_getsockopt (rep, ZMQ_MONITOR, monitor, &sz); + rc = zmq_getsockopt (rep, ZMQ_MONITOR, &monitor, &sz); assert (rc == 0); assert (monitor == listening_sock_monitor); @@ -116,7 +118,7 @@ int main (int argc, char *argv []) rc = zmq_setsockopt (rep, ZMQ_MONITOR, NULL, 0); assert (rc == 0); - rc = zmq_getsockopt (rep, ZMQ_MONITOR, monitor, &sz); + rc = zmq_getsockopt (rep, ZMQ_MONITOR, &monitor, &sz); assert (rc == 0); assert (monitor == listening_sock_monitor); @@ -126,7 +128,8 @@ int main (int argc, char *argv []) void *req = zmq_socket (ctx, ZMQ_REQ); assert (req); - rc = zmq_setsockopt (req, ZMQ_MONITOR, (void *)connecting_sock_monitor, sizeof (void *)); + monitor = connecting_sock_monitor; + rc = zmq_setsockopt (req, ZMQ_MONITOR, *(void **)&monitor, sizeof (void *)); assert (rc == 0); rc = zmq_connect (req, "tcp://127.0.0.1:5560");