Main Page   Compound List   File List   Compound Members   File Members  

TclXPCOMInvoke.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * The contents of this file are subject to the Mozilla Public License Version
00004  * 1.1 (the "License"); you may not use this file except in compliance with
00005  * the License. You may obtain a copy of the License at
00006  * http://www.mozilla.org/MPL/
00007  *
00008  * Software distributed under the License is distributed on an "AS IS" basis,
00009  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00010  * for the specific language governing rights and limitations under the
00011  * License.
00012  *
00013  * The Original Code is TclXPCOM.
00014  * 
00015  * The Initial Developer of the Original Code is Mark Follett.
00016  * Portions created by Mark Follett are Copyright (C) 2001-2002
00017  * Mark Follett.  All Rights Reserved.
00018  * 
00019  * Contributor(s):
00020  *     Mark Follett <mef123@myrealbox.com> (Original Author)
00021  *
00022  * Alternatively, the contents of this file may be used under the terms of
00023  * either the GNU General Public License Version 2 or later (the "GPL"), or
00024  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00025  * in which case the provisions of the GPL or the LGPL are applicable instead
00026  * of those above. If you wish to allow use of your version of this file only
00027  * under the terms of either the GPL or the LGPL, and not to allow others to
00028  * use your version of this file under the terms of the MPL, indicate your
00029  * decision by deleting the provisions above and replace them with the notice
00030  * and other provisions required by the GPL or the LGPL. If you do not delete
00031  * the provisions above, a recipient may use your version of this file under
00032  * the terms of any one of the MPL, the GPL or the LGPL.
00033  */
00034 
00041 #include "TclXPCOMPrivate.h"
00042 #include "nsString.h"
00043 
00044 
00045 #define INVOKE_BUFFERSIZE   16
00046 
00047 
00051 void
00052 PrepareVariant(
00053     nsXPTCVariant  *param,    
00054     nsXPTParamInfo *paraminfo 
00055 )
00056 {
00057     NS_PRECONDITION(param, "null pointer");
00058     NS_PRECONDITION(paraminfo, "null pointer");
00059 
00060     param->type = paraminfo->GetType();
00061     param->ClearFlags();
00062 
00063     if (paraminfo->IsOut())
00064     {
00065         param->SetPtrIsData();
00066         param->ptr = &param->val.p;
00067     } else
00068     {
00069         param->ptr = NULL;
00070     }
00071     
00072     if (param->type.IsPointer())
00073     {
00074         switch (param->type.TagPart())
00075         {
00076             case nsXPTType::T_ASTRING:
00077             case nsXPTType::T_DOMSTRING:
00078                 param->val.p = new nsString();
00079                 break;
00080 
00081             case nsXPTType::T_CSTRING:
00082             case nsXPTType::T_UTF8STRING:
00083                 param->val.p = new nsCString();
00084                 break;
00085 
00086             default:
00087                 param->val.p = NULL;
00088                 break;
00089         }
00090     }
00091 }
00092 
00093 
00100 int
00101 TclXPCOM_Invoke(
00102     Tcl_Interp       *interp,       
00103     Tcl_Obj          *CONST objv[], 
00104     nsISupports      *isupports,    
00105     nsIInterfaceInfo *interfaceinfo,
00106     PRUint16          methodindex   
00107 )
00108 {
00109     char str[128];
00110 
00111     int rv;
00112     nsresult res;
00113 
00114     Tcl_Obj *param;
00115 
00116     nsXPTCVariant  *variants;
00117     void           **params;
00118 
00119     nsXPTCVariant stackedvariants[INVOKE_BUFFERSIZE];
00120     void          *stackedparams[INVOKE_BUFFERSIZE];
00121 
00122     MethodInfo *minfo;
00123     PRUint8  i, paramcount;
00124     PRUint16 j, *tclparams;
00125     nsXPTParamInfo *paraminfos;
00126 
00127     NS_PRECONDITION(interp, "null pointer");
00128     NS_PRECONDITION(objv, "null pointer");
00129     NS_PRECONDITION(isupports, "null pointer");
00130     NS_PRECONDITION(interfaceinfo, "null pointer");
00131 
00132     minfo      = GetMethodInfo(interfaceinfo, methodindex);
00133     tclparams  = minfo->tclparams;
00134     paramcount = minfo->paramcount;
00135     paraminfos = minfo->paraminfos;
00136 
00137     if (paramcount > INVOKE_BUFFERSIZE)
00138     {
00139         variants = (nsXPTCVariant *)memmgr->Alloc(sizeof(nsXPTCVariant) * paramcount);
00140         params =           (void **)memmgr->Alloc(sizeof(void *) * paramcount);
00141     } else
00142     {
00143         variants = stackedvariants;
00144         params   = stackedparams;
00145     }
00146 
00147     for (i = 0; i < paramcount; i++)
00148     {
00149         PrepareVariant(&variants[i], &paraminfos[i]);
00150         params[i] = &variants[i].val;
00151     }
00152     
00153     /*
00154     TCL Calling C++
00155     1) write in and in/out parameters
00156     2) if writing fails (bad tcl script inputs), cleanup in and in/out parameters and return code
00157     3) call C++
00158     4) if failed, free in and in/out parameters
00159     5) read in/out and out parameters
00160     6) free in, in/out, and out (not shared) parameters
00161     7) return code
00162     */
00163 
00164     //1) write in and in/out parameters
00165     for (i = 0; i < paramcount; i++)
00166     {
00167         if (tclparams[i] & PARAM_IS_SKIPPED)
00168         {
00169             continue;
00170         }
00171 
00172         j = (tclparams[i] & PARAM_INDEX_MASK);
00173 
00174         if (paraminfos[i].IsIn() && !paraminfos[i].IsDipper())
00175         {
00176             if (paraminfos[i].IsOut())
00177             {
00178                 param = Tcl_ObjGetVar2(interp, objv[j], NULL, 0);
00179                 if (param == NULL)
00180                 {
00181                     Tcl_ResetResult(interp);
00182                     Tcl_AppendResult(interp, "in/out variable \"", Tcl_GetString(objv[j]), "\" must be set", NULL);
00183                     rv = TCL_ERROR;
00184                     goto done;
00185                 }
00186             } else
00187             {
00188                 param = objv[j];
00189             }
00190 
00191             rv = Tcl2Native(interp, param, params, params[i], &variants[i].type, tclparams[i] & PARAM_IS_SHARED_IN, interfaceinfo, methodindex, &paraminfos[i]);
00192 
00193             //2) if writing fails (bad tcl script inputs), cleanup in and in/out parameters and return code
00194             if (rv != TCL_OK)
00195             {
00196                 sprintf(str, "\nwhile writing in parameter #%d", j);
00197                 Tcl_AddObjErrorInfo(interp, str, -1);
00198                 goto done;
00199             }
00200         }
00201     }
00202 
00203     //3) call C++
00204     res = XPTC_InvokeByIndex(isupports, (PRUint32)methodindex, (PRUint32)paramcount, variants);
00205 
00206     Tcl_SetVar2Ex(interp, TCLXPCOM_LASTRESULTVARNAME, NULL, Tcl_NewLongObj((long)res), TCL_GLOBAL_ONLY);
00207 
00208     //4) if failed, free in and in/out parameters
00209     if (NS_SUCCEEDED(res))
00210     {
00211         rv = TCL_OK;
00212     } else
00213     {
00214         TclXPCOM_SetError(interp, res);
00215         rv = TCL_ERROR;
00216         goto done;
00217     }
00218     
00219     //5) read in/out and out parameters
00220     for (i = 0; i < paramcount; i++)
00221     {
00222         if (tclparams[i] & PARAM_IS_SKIPPED)
00223         {
00224             continue;
00225         }
00226 
00227         j = (tclparams[i] & PARAM_INDEX_MASK);
00228         
00229         if (paraminfos[i].IsOut() || paraminfos[i].IsDipper())
00230         {
00231             res = Native2Tcl(params, params[i], &variants[i].type, interfaceinfo, methodindex, &paraminfos[i], &param);
00232 
00233             if (NS_FAILED(res))
00234             {
00235                 TclXPCOM_SetError(interp, res);
00236 
00237                 if (paraminfos[i].IsRetval())
00238                 {
00239                     sprintf(str, "\nwhile reading return parameter");
00240                 } else
00241                 {
00242                     sprintf(str, "\nwhile reading out parameter #%d", j);
00243                 }
00244                 Tcl_AddObjErrorInfo(interp, str, -1);
00245                 rv = TCL_ERROR;
00246                 goto done;
00247             }
00248 
00249             if (paraminfos[i].IsRetval())
00250             {
00251                 Tcl_SetObjResult(interp, param);
00252             } else
00253             {
00254                 Tcl_ObjSetVar2(interp, objv[j], NULL, param, 0);
00255             }
00256         }
00257     }
00258 
00259 done:
00260     //6) free in, in/out, and out (but not shared) parameters
00261     for (i = 0; i < paramcount; i++)
00262     {
00263         CleanupParam(params, params[i], &variants[i].type, interfaceinfo, methodindex, &paraminfos[i]);
00264     }
00265     
00266     if (paramcount > INVOKE_BUFFERSIZE)
00267     {
00268         memmgr->Free(variants);
00269         memmgr->Free(params);
00270     }
00271 
00272     return rv;
00273 }
00274 
00275 

Generated on Fri Jun 14 23:25:51 2002 for TclXPCOM by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002