From 2c1ef1c682e01aabec511223b52d9d845063d6dc Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 4 Aug 2020 18:18:59 +0200 Subject: [PATCH] Redefine opaque types as pointers to structs. Warning: This may break source compatibility! This fixes casting-related errors in the C++ wrapper related to passing a lo::ServerThread object to lo::Address::send_from, see https://github.com/radarsat1/liblo/issues/101 To summarize, the C++ template cannot differentiate between lo_server and lo_server_thread because they are both (void*), and therefore performs the wrong cast. This can be fixed by making these opaque types pointers to different types instead of all pointing to void. It could be possible to redefine just these types, but this patch takes this to the full extent and redefines all the opaque pointers so that they are different types, to avoid any potential similar issues. It is more correct, but could lead to incompatibility with older code, particularly because it redefines the lo_method_handler prototype. --- examples/example_server.c | 16 ++++++++-------- examples/example_tcp_echo_server.c | 8 ++++---- examples/nonblocking_server_example.c | 12 ++++++------ lo/lo_cpp.h | 2 +- lo/lo_types.h | 14 +++++++------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/example_server.c b/examples/example_server.c index 910b3ffd..ef3fa75e 100644 --- a/examples/example_server.c +++ b/examples/example_server.c @@ -26,16 +26,16 @@ int done = 0; void error(int num, const char *m, const char *path); int generic_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); int foo_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); int blobtest_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); int quit_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); int main() { @@ -79,7 +79,7 @@ void error(int num, const char *msg, const char *path) /* catch any incoming messages and display them. returning 1 means that the * message has not been fully handled and the server should try other methods */ int generic_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { int i; @@ -96,7 +96,7 @@ int generic_handler(const char *path, const char *types, lo_arg ** argv, } int foo_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { /* example showing pulling the argument values out of the argv array */ printf("%s <- f:%f, i:%d\n\n", path, argv[0]->f, argv[1]->i); @@ -106,7 +106,7 @@ int foo_handler(const char *path, const char *types, lo_arg ** argv, } int blobtest_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { /* example showing how to get data for a blob */ int i, size = argv[0]->blob.size; @@ -136,7 +136,7 @@ int blobtest_handler(const char *path, const char *types, lo_arg ** argv, } int quit_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { done = 1; printf("quiting\n\n"); diff --git a/examples/example_tcp_echo_server.c b/examples/example_tcp_echo_server.c index 11ff1b99..12a3a052 100644 --- a/examples/example_tcp_echo_server.c +++ b/examples/example_tcp_echo_server.c @@ -36,10 +36,10 @@ int count = 0; void error(int num, const char *m, const char *path); int echo_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); int quit_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); void ctrlc(int sig) { @@ -114,7 +114,7 @@ void error(int num, const char *msg, const char *path) /* catch any incoming messages, display them, and send them * back. */ int echo_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { int i; lo_message m = (lo_message)data; @@ -159,7 +159,7 @@ int echo_handler(const char *path, const char *types, lo_arg ** argv, } int quit_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { done = 1; printf("quitting\n\n"); diff --git a/examples/nonblocking_server_example.c b/examples/nonblocking_server_example.c index 25ef6c4a..897309ad 100644 --- a/examples/nonblocking_server_example.c +++ b/examples/nonblocking_server_example.c @@ -34,13 +34,13 @@ int done = 0; void error(int num, const char *m, const char *path); int generic_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); int foo_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); int quit_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data); + int argc, lo_message data, void *user_data); void read_stdin(void); @@ -151,7 +151,7 @@ void error(int num, const char *msg, const char *path) /* catch any incoming messages and display them. returning 1 means that the * message has not been fully handled and the server should try other methods */ int generic_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { int i; @@ -168,7 +168,7 @@ int generic_handler(const char *path, const char *types, lo_arg ** argv, } int foo_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { /* example showing pulling the argument values out of the argv array */ printf("%s <- f:%f, i:%d\n\n", path, argv[0]->f, argv[1]->i); @@ -178,7 +178,7 @@ int foo_handler(const char *path, const char *types, lo_arg ** argv, } int quit_handler(const char *path, const char *types, lo_arg ** argv, - int argc, void *data, void *user_data) + int argc, lo_message data, void *user_data) { done = 1; printf("quiting\n\n"); diff --git a/lo/lo_cpp.h b/lo/lo_cpp.h index 31451440..5effadf0 100644 --- a/lo/lo_cpp.h +++ b/lo/lo_cpp.h @@ -50,7 +50,7 @@ std::unique_ptr(new handler_type(h))); \ lo_method m = _add_method(path, types, \ [](const char *path, const char *types, \ - lo_arg **argv, int argc, void *msg, \ + lo_arg **argv, int argc, lo_message msg, \ void *data)->int \ { \ r1 (*static_cast*>(data)) args; \ diff --git a/lo/lo_types.h b/lo/lo_types.h index 59afcf05..bc240e94 100644 --- a/lo/lo_types.h +++ b/lo/lo_types.h @@ -42,14 +42,14 @@ extern "C" { * * Created by calls to lo_address_new() or lo_address_new_from_url(). */ -typedef void *lo_address; +typedef struct lo_address_ {} *lo_address; /** * \brief A object to store an opaque binary data object. * * Can be passed over OSC using the 'b' type. Created by calls to lo_blob_new(). */ -typedef void *lo_blob; +typedef struct lo_blob_ {} *lo_blob; /** * \brief A low-level object used to represent messages passed over OSC. @@ -57,7 +57,7 @@ typedef void *lo_blob; * Created by calls to lo_message_new(), arguments can be added with calls to * lo_message_add_*(). */ -typedef void *lo_message; +typedef struct lo_message_ {} *lo_message; /** * \brief A low-level object used to represent bundles of messages passed over @@ -66,7 +66,7 @@ typedef void *lo_message; * Created by calls to lo_bundle_new(), messages can be added with calls to * lo_bundle_add_message(). */ -typedef void *lo_bundle; +typedef struct lo_bundle_ {} *lo_bundle; /** * \brief An object representing an method on a server. @@ -74,7 +74,7 @@ typedef void *lo_bundle; * Returned by calls to lo_server_thread_add_method() and * lo_server_add_method(). */ -typedef void *lo_method; +typedef struct lo_method_ {} *lo_method; /** * \brief An object representing an instance of an OSC server. @@ -82,14 +82,14 @@ typedef void *lo_method; * Created by calls to lo_server_new(). If you wish to have the server * operate in a background thread, use lo_server_thread instead. */ -typedef void *lo_server; +typedef struct lo_server_ {} *lo_server; /** * \brief An object representing a thread containing an OSC server. * * Created by calls to lo_server_thread_new(). */ -typedef void *lo_server_thread; +typedef struct lo_server_thread_ {} *lo_server_thread; /** * \brief A callback function to receive notification of an error in a server or