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;
 }
 

Reply via email to