diff options
author | Logan Johnson <ljohnson@users.sourceforge.net> | 2003-04-29 16:08:16 +0000 |
---|---|---|
committer | Logan Johnson <ljohnson@users.sourceforge.net> | 2003-04-29 16:08:16 +0000 |
commit | 3fd12995c75720d4a759cd1edc66f2eb97425a63 (patch) | |
tree | a9b85492f85de892a77502b2611b5ef232c9dce1 /Source | |
parent | 9d2567b1f36ea4d981b98aa2483c458dde2df4bd (diff) | |
download | swig-3fd12995c75720d4a759cd1edc66f2eb97425a63.tar.gz |
A little more work on the Ruby support for C++ polymorphism. Exception
handling almost works...
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@4745 626c5289-ae23-0410-ae9c-e8d60b6d4f22
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Modules/ruby.cxx | 145 |
1 files changed, 91 insertions, 54 deletions
diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 39727b54c..fdbc02f3a 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -2123,6 +2123,76 @@ public: * * --------------------------------------------------------------- */ + void exceptionSafeMethodCall(Node *n, Wrapper *w, int argc, String *args) { + + Wrapper *body = NewWrapper(); + Wrapper *rescue = NewWrapper(); + + String *methodName = Getattr(n, "sym:name"); + String *bodyName = NewStringf("%s_body", methodName); + String *rescueName = NewStringf("%s_rescue", methodName); + + // Check for an exception typemap of some kind + String *tm = Swig_typemap_lookup_new("director:except", n, "result", 0); + if (!tm) { + tm = Getattr(n, "feature:director:except"); + } + + if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0)) + { + // Function body + Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName); + Wrapper_add_localv(body, "args", "swig_body_args *", "args", "= reinterpret_cast<swig_body_args *>(data)", NIL); + Printv(body->code, "return rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL); + Printv(body->code, "}", NIL); + + // Exception handler + Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName); + Replaceall(tm, "$error", "error"); + Printv(rescue->code, Str(tm), "\n", NIL); + Printv(rescue->code, "}", NIL); + + // Main code + Wrapper_add_localv(w, "args", "swig_body_args", "args", NIL); + Printv(w->code, "args.recv = __get_self();\n", NIL); + Printf(w->code, "args.id = rb_intern(\"%s\");\n", methodName); + Printf(w->code, "args.argc = %d;\n", argc); + if (argc > 0) { + Wrapper_add_localv(w, "i", "int", "i", NIL); + Printf(w->code, "args.argv = new VALUE[%d];\n", argc); + Printf(w->code, "for (i = 0; i < %d; i++) {\n", argc); + Printv(w->code, "args.argv[i] = Qnil;\n", NIL); + Printv(w->code, "}\n", NIL); + } else { + Printv(w->code, "args.argv = 0;\n", NIL); + } + Printf(w->code, + "result = rb_rescue2((VALUE(*)(ANYARGS)) %s, reinterpret_cast<VALUE>(&args), (VALUE(*)(ANYARGS)) %s, reinterpret_cast<VALUE>(&args), rb_eStandardError, 0);\n", + bodyName, rescueName); + if (argc > 0) { + Printv(w->code, "delete [] args.argv;\n", NIL); + } + + // Dump wrapper code + Wrapper_print(body, f_directors); + Wrapper_print(rescue, f_directors); + } + else + { + if (argc > 0) { + Printf(w->code, "result = rb_funcall(__get_self(), rb_intern(\"%s\"), %d%s);\n", methodName, argc, args); + } else { + Printf(w->code, "result = rb_funcall(__get_self(), rb_intern(\"%s\"), 0, NULL);\n", methodName); + } + } + + // Clean up + Delete(bodyName); + Delete(rescueName); + DelWrapper(body); + DelWrapper(rescue); + } + virtual int classDirectorMethod(Node *n, Node *parent, String *super) { int is_void = 0; int is_pointer = 0; @@ -2188,7 +2258,6 @@ public: /* attach typemaps to arguments (C/C++ -> Ruby) */ String *arglist = NewString(""); - String* parse_args = NewString(""); Swig_typemap_attach_parms("in", l, w); Swig_typemap_attach_parms("inv", l, w); @@ -2213,31 +2282,20 @@ public: if (Getattr(p, "tmap:argoutv") != 0) outputs++; - String* pname = Getattr(p, "name"); - String* ptype = Getattr(p, "type"); + String* parameterName = Getattr(p, "name"); + String* parameterType = Getattr(p, "type"); Putc(',',arglist); if ((tm = Getattr(p, "tmap:inv")) != 0) { - String* parse = Getattr(p, "tmap:inv:parse"); - if (!parse) { - sprintf(source, "obj%d", idx++); - Replaceall(tm, "$input", source); - Replaceall(tm, "$owner", "0"); - Printv(wrap_args, tm, "\n", NIL); - Wrapper_add_localv(w, source, "VALUE", source, "= 0", NIL); - Printv(arglist, source, NIL); - Putc('O', parse_args); - } else { - Printf(parse_args, "%s", parse); - Replaceall(tm, "$input", pname); - Replaceall(tm, "$owner", "0"); - if (Len(tm) == 0) Append(tm, pname); - Printf(arglist, "%s", tm); - } + sprintf(source, "obj%d", idx++); + Replaceall(tm, "$input", source); + Replaceall(tm, "$owner", "0"); + Printv(wrap_args, tm, "\n", NIL); + Wrapper_add_localv(w, source, "VALUE", source, "= 0", NIL); + Printv(arglist, source, NIL); p = Getattr(p, "tmap:inv:next"); continue; - } else - if (Cmp(ptype, "void")) { + } else if (Cmp(parameterType, "void")) { /** * Special handling for pointers to other C++ director classes. * Ideally this would be left to a typemap, but there is currently no @@ -2248,32 +2306,32 @@ public: * do something similar. Perhaps a new default typemap (in addition * to SWIGTYPE) called DIRECTORTYPE? */ - if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) { + if (SwigType_ispointer(parameterType) || SwigType_isreference(parameterType)) { Node *module = Getattr(parent, "module"); - Node *target = Swig_directormap(module, ptype); + Node *target = Swig_directormap(module, parameterType); sprintf(source, "obj%d", idx++); String *nonconst = 0; /* strip pointer/reference --- should move to Swig/stype.c */ - String *nptype = NewString(Char(ptype)+2); + String *nptype = NewString(Char(parameterType)+2); /* name as pointer */ - String *ppname = Copy(pname); - if (SwigType_isreference(ptype)) { + String *ppname = Copy(parameterName); + if (SwigType_isreference(parameterType)) { Insert(ppname,0,"&"); } /* if necessary, cast away const since Ruby doesn't support it! */ if (SwigType_isconst(nptype)) { - nonconst = NewStringf("nc_tmp_%s", pname); - String *nonconst_i = NewStringf("= const_cast<%s>(%s)", SwigType_lstr(ptype, 0), ppname); - Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL); + nonconst = NewStringf("nc_tmp_%s", parameterName); + String *nonconst_i = NewStringf("= const_cast<%s>(%s)", SwigType_lstr(parameterType, 0), ppname); + Wrapper_add_localv(w, nonconst, SwigType_lstr(parameterType, 0), nonconst, nonconst_i, NIL); Delete(nonconst_i); Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number, - "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(ptype, pname), classname, name); + "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(parameterType, parameterName), classname, name); } else { nonconst = Copy(ppname); } Delete(nptype); Delete(ppname); - String *mangle = SwigType_manglestr(ptype); + String *mangle = SwigType_manglestr(parameterType); if (target) { String *director = NewStringf("director_%s", mangle); Wrapper_add_localv(w, director, "__DIRECTOR__ *", director, "= 0", NIL); @@ -2295,12 +2353,11 @@ public: // source, nonconst, base); Printv(arglist, source, NIL); } - Putc('O', parse_args); Delete(mangle); Delete(nonconst); } else { Swig_warning(WARN_TYPEMAP_INV_UNDEF, input_file, line_number, - "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0), classname, name); + "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(parameterType, 0), classname, name); status = SWIG_NOWRAP; break; } @@ -2338,27 +2395,8 @@ public: /* wrap complex arguments to PyObjects */ Printv(w->code, wrap_args, NIL); - String *pyname = Getattr(n,"sym:name"); - /* pass the method call on to the Ruby object */ - if (Len(parse_args) > 0) { - Printf(w->code, "result = rb_funcall(__get_self(), rb_intern(\"%s\"), %d%s);\n", pyname, 0, arglist); - } else { - Printf(w->code, "result = rb_funcall(__get_self(), rb_intern(\"%s\"), 0, NULL);\n", pyname); - } - - /* exception handling */ - tm = Swig_typemap_lookup_new("director:except", n, "result", 0); - if (!tm) { - tm = Getattr(n, "feature:director:except"); - } - if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { - Printf(w->code, "if (result == NULL) {\n"); - Printf(w->code, " PyObject *error = PyErr_Occurred();\n"); - Replaceall(tm, "$error", "error"); - Printv(w->code, Str(tm), "\n", NIL); - Printf(w->code, "}\n"); - } + exceptionSafeMethodCall(n, w, idx, arglist); /* * Ruby method may return a simple object, or an Array of objects. @@ -2453,7 +2491,6 @@ public: /* clean up */ Delete(wrap_args); - Delete(parse_args); Delete(arglist); Delete(rtype); Delete(return_type); |