00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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 = ¶m->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], ¶minfos[i]);
00150 params[i] = &variants[i].val;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
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, ¶minfos[i]);
00192
00193
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
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
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
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, ¶minfos[i], ¶m);
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
00261 for (i = 0; i < paramcount; i++)
00262 {
00263 CleanupParam(params, params[i], &variants[i].type, interfaceinfo, methodindex, ¶minfos[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