THRIFT-3273 c_glib: Generated code tries to convert between function and void pointers
Client: c_glib
Patch: Simon South <ssouth@simonsouth.com>
This closes #568
diff --git a/compiler/cpp/src/generate/t_c_glib_generator.cc b/compiler/cpp/src/generate/t_c_glib_generator.cc
index dfdd4ef..a32b224 100644
--- a/compiler/cpp/src/generate/t_c_glib_generator.cc
+++ b/compiler/cpp/src/generate/t_c_glib_generator.cc
@@ -1882,6 +1882,10 @@
string handler_class_name = this->nspace + service_name_ + "Handler";
string handler_class_name_lc = initial_caps_to_underscores(handler_class_name);
+ string process_function_type_name = class_name + "ProcessFunction";
+ string process_function_def_type_name =
+ class_name_lc + "_process_function_def";
+
string function_name;
string args_indent;
@@ -1965,11 +1969,67 @@
<< "," << endl << args_indent << parent_type_name << ");" << endl << endl;
// Generate the processor's processing-function type
- function_name = class_name + "ProcessFunction";
- args_indent = string(function_name.length() + 23, ' ');
- f_service_ << "typedef gboolean (* " << function_name << ") (" << class_name << " *, " << endl
- << args_indent << "gint32," << endl << args_indent << "ThriftProtocol *," << endl
- << args_indent << "ThriftProtocol *," << endl << args_indent << "GError **);" << endl
+ args_indent = string(process_function_type_name.length() + 23, ' ');
+ f_service_ << "typedef gboolean (* " << process_function_type_name << ") ("
+ << class_name << " *, " << endl
+ << args_indent << "gint32," << endl
+ << args_indent << "ThriftProtocol *," << endl
+ << args_indent << "ThriftProtocol *," << endl
+ << args_indent << "GError **);" << endl
+ << endl;
+
+ // Generate the processor's processing-function-definition type
+ f_service_ << "typedef struct" << endl
+ << "{" << endl;
+ indent_up();
+ f_service_ << indent() << "gchar *name;" << endl
+ << indent() << process_function_type_name << " function;" << endl;
+ indent_down();
+ f_service_ << "} " << process_function_def_type_name << ";" << endl
+ << endl;
+
+ // Generate forward declarations of the processor's processing functions so we
+ // can refer to them in the processing-function-definition struct below and
+ // keep all of the processor's declarations in one place
+ for (function_iter = functions.begin();
+ function_iter != functions.end();
+ ++function_iter) {
+ function_name = class_name_lc + "_process_"
+ + initial_caps_to_underscores((*function_iter)->get_name());
+
+ args_indent = string(function_name.length() + 2, ' ');
+ f_service_ << "static gboolean" << endl
+ << function_name << " ("
+ << class_name << " *," << endl
+ << args_indent << "gint32," << endl
+ << args_indent << "ThriftProtocol *," << endl
+ << args_indent << "ThriftProtocol *," << endl
+ << args_indent << "GError **);" << endl;
+ }
+ f_service_ << endl;
+
+ // Generate the processor's processing-function definitions
+ f_service_ << indent() << "static " << process_function_def_type_name << endl
+ << indent() << class_name_lc << "_process_function_defs["
+ << functions.size() << "] = {" << endl;
+ indent_up();
+ for (function_iter = functions.begin();
+ function_iter != functions.end();
+ ++function_iter) {
+ string service_function_name = (*function_iter)->get_name();
+ string process_function_name = class_name_lc + "_process_"
+ + initial_caps_to_underscores(service_function_name);
+
+ f_service_ << indent() << "{" << endl;
+ indent_up();
+ f_service_ << indent() << "\"" << service_function_name << "\"," << endl
+ << indent() << process_function_name << endl;
+ indent_down();
+ f_service_ << indent() << "}"
+ << (function_iter == --functions.end() ? "" : ",") << endl;
+ }
+ indent_down();
+ f_service_ << indent() << "};" << endl
<< endl;
// Generate the processor's processing functions
@@ -2308,7 +2368,8 @@
<< endl << args_indent << "gint32 sequence_id," << endl << args_indent
<< "GError **error)" << endl;
scope_up(f_service_);
- f_service_ << indent() << class_name << "ProcessFunction process_function; " << endl;
+ f_service_ << indent() << class_name_lc << "_process_function_def *"
+ << "process_function_def;" << endl;
f_service_ << indent() << "gboolean dispatch_result = FALSE;" << endl << endl << indent()
<< class_name << " *self = " << class_name_uc << " (dispatch_processor);" << endl;
f_service_ << indent() << parent_class_name << "Class "
@@ -2317,14 +2378,18 @@
f_service_ << indent() << "g_type_class_peek_parent (" << class_name_uc << "_GET_CLASS (self));"
<< endl;
indent_down();
- f_service_ << endl << indent() << "process_function = g_hash_table_lookup ("
- << "self->process_map, method_name);" << endl << indent()
- << "if (process_function != NULL)" << endl;
+ f_service_ << endl
+ << indent() << "process_function_def = "
+ << "g_hash_table_lookup (self->process_map, method_name);" << endl
+ << indent() << "if (process_function_def != NULL)" << endl;
scope_up(f_service_);
- args_indent = indent() + string(39, ' ');
- f_service_ << indent() << "dispatch_result = (*process_function) (self," << endl << args_indent
- << "sequence_id," << endl << args_indent << "input_protocol," << endl << args_indent
- << "output_protocol," << endl << args_indent << "error);" << endl;
+ args_indent = indent() + string(53, ' ');
+ f_service_ << indent() << "dispatch_result = "
+ << "(*process_function_def->function) (self," << endl
+ << args_indent << "sequence_id," << endl
+ << args_indent << "input_protocol," << endl
+ << args_indent << "output_protocol," << endl
+ << args_indent << "error);" << endl;
scope_down(f_service_);
f_service_ << indent() << "else" << endl;
scope_up(f_service_);
@@ -2435,18 +2500,26 @@
f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)"
<< endl;
scope_up(f_service_);
+ if (functions.size() > 0) {
+ f_service_ << indent() << "guint index;" << endl
+ << endl;
+ }
f_service_ << indent() << "self->handler = NULL;" << endl << indent()
<< "self->process_map = "
- "g_hash_table_new (g_str_hash, g_str_equal);" << endl << endl;
- args_indent = string(21, ' ');
- for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
- string service_function_name = (*function_iter)->get_name();
- string process_function_name = class_name_lc + "_process_"
- + initial_caps_to_underscores(service_function_name);
-
+ "g_hash_table_new (g_str_hash, g_str_equal);" << endl;
+ if (functions.size() > 0) {
+ args_indent = string(21, ' ');
+ f_service_ << endl
+ << indent() << "for (index = 0; index < "
+ << functions.size() << "; index += 1)" << endl;
+ indent_up();
f_service_ << indent() << "g_hash_table_insert (self->process_map," << endl
- << indent() + args_indent + "\"" << service_function_name << "\", " << endl
- << indent() + args_indent + process_function_name << ");" << endl;
+ << indent() << args_indent
+ << class_name_lc << "_process_function_defs[index].name," << endl
+ << indent() << args_indent
+ << "&" << class_name_lc << "_process_function_defs[index]" << ");"
+ << endl;
+ indent_down();
}
scope_down(f_service_);
f_service_ << endl;