Avoid Clownfish::Host on more callbacks. Use Perl C API directly in callback wrapper functions for methods which return values, avoiding Clownfish::Host.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/4460c149 Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/4460c149 Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/4460c149 Branch: refs/heads/master Commit: 4460c1499500cb4f431da47daed801c7926a95f4 Parents: 0bf286d Author: Marvin Humphrey <[email protected]> Authored: Sat Nov 10 10:22:29 2012 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Tue Nov 13 18:18:28 2012 -0800 ---------------------------------------------------------------------- clownfish/compiler/src/CFCPerlMethod.c | 94 ++++++++++++++++++++------- 1 files changed, 71 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/4460c149/clownfish/compiler/src/CFCPerlMethod.c ---------------------------------------------------------------------- diff --git a/clownfish/compiler/src/CFCPerlMethod.c b/clownfish/compiler/src/CFCPerlMethod.c index 5b47e69..0c65a72 100644 --- a/clownfish/compiler/src/CFCPerlMethod.c +++ b/clownfish/compiler/src/CFCPerlMethod.c @@ -760,40 +760,75 @@ S_primitive_callback_def(CFCMethod *method, const char *callback_params, const char *refcount_mods) { const char *override_sym = CFCMethod_full_override_sym(method); const char *params = CFCParamList_to_c(CFCMethod_get_param_list(method)); + char *callback_start = S_callback_start(method); CFCType *return_type = CFCMethod_get_return_type(method); const char *ret_type_str = CFCType_to_c(return_type); - char cb_func_name[40]; - if (CFCType_is_floating(return_type)) { - strcpy(cb_func_name, "cfish_Host_callback_f64"); - } - else if (CFCType_is_integer(return_type)) { - strcpy(cb_func_name, "cfish_Host_callback_i64"); + const char *micro_sym = CFCMethod_micro_sym(method); + char *assign_retval = NULL; + + if (CFCType_is_integer(return_type)) { + int width = CFCType_get_width(return_type); + if (width != 0 && width <= 4) { + char pattern[] = " %s retval = (%s)SvIV(return_sv);\n"; + size_t size = sizeof(pattern) + (2 * strlen(ret_type_str)) + 20; + assign_retval = (char*)MALLOCATE(size); + sprintf(assign_retval, pattern, ret_type_str, ret_type_str); + } + else { + char pattern[] = + " %s retval = (sizeof(IV) >= sizeof(%s))\n" + " ? (%s)SvIV(return_sv) : (%s)SvNV(return_sv);\n"; + size_t size = sizeof(pattern) + (4 * strlen(ret_type_str)) + 20; + assign_retval = (char*)MALLOCATE(size); + sprintf(assign_retval, pattern, ret_type_str, ret_type_str, + ret_type_str, ret_type_str); + } } - else if (strcmp(ret_type_str, "void*") == 0) { - strcpy(cb_func_name, "cfish_Host_callback_host"); + else if (CFCType_is_floating(return_type)) { + char pattern[] = " %s retval = (%s)SvNV(return_sv);\n"; + size_t size = sizeof(pattern) + (2 * strlen(ret_type_str)) + 20; + assign_retval = (char*)MALLOCATE(size); + sprintf(assign_retval, pattern, ret_type_str, ret_type_str); } else { - CFCUtil_die("unrecognized type: %s", ret_type_str); + CFCUtil_die("Unexpected type: %s", ret_type_str); } char pattern[] = "%s\n" "%s(%s) {\n" - " return (%s)%s(%s);%s\n" + "%s" + " int _count = call_method(\"%s\", G_SCALAR);\n" + " if (_count != 1) {\n" + " CFISH_THROW(CFISH_ERR, \"Bad number of return vals from '%%s': %%i32\",\n" + " \"%s\", (int32_t)_count);\n" + " }\n" + " SPAGAIN;\n" + " SV *return_sv = POPs;\n" + " PUTBACK;\n" + "%s" + " FREETMPS;\n" + " LEAVE;%s\n" + " return retval;\n" "}\n"; + size_t size = sizeof(pattern) + strlen(ret_type_str) + strlen(override_sym) + strlen(params) - + strlen(ret_type_str) - + strlen(cb_func_name) - + strlen(callback_params) + + strlen(callback_start) + + strlen(micro_sym) + + strlen(micro_sym) + + strlen(assign_retval) + strlen(refcount_mods) - + 20; + + 30; char *callback_def = (char*)MALLOCATE(size); sprintf(callback_def, pattern, ret_type_str, override_sym, params, - ret_type_str, cb_func_name, callback_params, refcount_mods); + callback_start, micro_sym, micro_sym, assign_retval, + refcount_mods); + FREEMEM(assign_retval); + FREEMEM(callback_start); return callback_def; } @@ -802,11 +837,10 @@ S_obj_callback_def(CFCMethod *method, const char *callback_params, const char *refcount_mods) { const char *override_sym = CFCMethod_full_override_sym(method); const char *params = CFCParamList_to_c(CFCMethod_get_param_list(method)); + char *callback_start = S_callback_start(method); CFCType *return_type = CFCMethod_get_return_type(method); const char *ret_type_str = CFCType_to_c(return_type); - const char *cb_func_name = CFCType_is_string_type(return_type) - ? "cfish_Host_callback_str" - : "cfish_Host_callback_obj"; + const char *micro_sym = CFCMethod_micro_sym(method); char *nullable_check = CFCUtil_strdup(""); if (!CFCType_nullable(return_type)) { @@ -823,26 +857,40 @@ S_obj_callback_def(CFCMethod *method, const char *callback_params, char pattern[] = "%s\n" "%s(%s) {\n" - " %s retval = (%s)%s(%s);%s%s\n" + "%s" + " int _count = call_method(\"%s\", G_SCALAR);\n" + " if (_count != 1) {\n" + " CFISH_THROW(CFISH_ERR, \"Bad number of return vals from '%%s': %%i32\",\n" + " \"%s\", (int32_t)_count);\n" + " }\n" + " SPAGAIN;\n" + " SV *return_sv = POPs;\n" + " PUTBACK;\n" + " %s retval = (%s)XSBind_perl_to_cfish(return_sv);\n" + " FREETMPS;\n" + " LEAVE;%s%s\n" " return retval;\n" "}\n"; + size_t size = sizeof(pattern) + strlen(ret_type_str) + strlen(override_sym) + strlen(params) + + strlen(callback_start) + + strlen(micro_sym) + + strlen(micro_sym) + strlen(ret_type_str) + strlen(ret_type_str) - + strlen(cb_func_name) - + strlen(callback_params) + strlen(nullable_check) + strlen(refcount_mods) + 30; char *callback_def = (char*)MALLOCATE(size); sprintf(callback_def, pattern, ret_type_str, override_sym, params, - ret_type_str, ret_type_str, cb_func_name, callback_params, - nullable_check, refcount_mods); + callback_start, micro_sym, micro_sym, ret_type_str, ret_type_str, + refcount_mods, nullable_check); FREEMEM(nullable_check); + FREEMEM(callback_start); return callback_def; }
