Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 632de27

Browse files
committed
The Tcl_Obj patch discussed on the patches list.
This was originally submitted by Martin von Loewis as part of his Unicode patch; all I did was add special cases for Python int and float objects and rearrange the object type tests somewhat to speed up the common cases (string, int, float, tuple, unicode, object).
1 parent e4fb958 commit 632de27

1 file changed

Lines changed: 77 additions & 82 deletions

File tree

Modules/_tkinter.c

Lines changed: 77 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,47 @@ Split(list)
425425
return v;
426426
}
427427

428+
static Tcl_Obj*
429+
AsObj(value)
430+
PyObject *value;
431+
{
432+
Tcl_Obj *result;
433+
434+
if (PyString_Check(value))
435+
return Tcl_NewStringObj(PyString_AS_STRING(value),
436+
PyString_GET_SIZE(value));
437+
else if (PyInt_Check(value))
438+
return Tcl_NewLongObj(PyInt_AS_LONG(value));
439+
else if (PyFloat_Check(value))
440+
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
441+
else if (PyTuple_Check(value)) {
442+
Tcl_Obj **argv = (Tcl_Obj**)
443+
ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
444+
int i;
445+
if(!argv)
446+
return 0;
447+
for(i=0;i<PyTuple_Size(value);i++)
448+
argv[i] = AsObj(PyTuple_GetItem(value,i));
449+
result = Tcl_NewListObj(PyTuple_Size(value), argv);
450+
ckfree(FREECAST argv);
451+
return result;
452+
}
453+
else if (PyUnicode_Check(value)) {
454+
PyObject* utf8 = PyUnicode_AsUTF8String (value);
455+
if (!utf8)
456+
return 0;
457+
return Tcl_NewStringObj (PyString_AS_STRING (utf8),
458+
PyString_GET_SIZE (utf8));
459+
}
460+
else {
461+
PyObject *v = PyObject_Str(value);
462+
if (!v)
463+
return 0;
464+
result = AsObj(v);
465+
Py_DECREF(v);
466+
return result;
467+
}
468+
}
428469

429470

430471
/**** Tkapp Object ****/
@@ -523,111 +564,65 @@ Tkapp_Call(self, args)
523564
PyObject *self;
524565
PyObject *args;
525566
{
526-
/* This is copied from Merge() */
527-
PyObject *tmp = NULL;
528-
char *argvStore[ARGSZ];
529-
char **argv = NULL;
530-
int fvStore[ARGSZ];
531-
int *fv = NULL;
532-
int argc = 0, i;
533-
PyObject *res = NULL; /* except this has a different type */
534-
Tcl_CmdInfo info; /* and this is added */
535-
Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
567+
Tcl_Obj *objStore[ARGSZ];
568+
Tcl_Obj **objv = NULL;
569+
int objc = 0, i;
570+
PyObject *res = NULL;
571+
Tcl_Interp *interp = Tkapp_Interp(self);
572+
/* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
573+
int flags = TCL_EVAL_DIRECT;
536574

537-
if (!(tmp = PyList_New(0)))
538-
return NULL;
539-
540-
argv = argvStore;
541-
fv = fvStore;
575+
objv = objStore;
542576

543577
if (args == NULL)
544-
argc = 0;
578+
objc = 0;
545579

546580
else if (!PyTuple_Check(args)) {
547-
argc = 1;
548-
fv[0] = 0;
549-
argv[0] = AsString(args, tmp);
581+
objc = 1;
582+
objv[0] = AsObj(args);
583+
if (objv[0] == 0)
584+
goto finally;
585+
Tcl_IncrRefCount(objv[0]);
550586
}
551587
else {
552-
argc = PyTuple_Size(args);
588+
objc = PyTuple_Size(args);
553589

554-
if (argc > ARGSZ) {
555-
argv = (char **)ckalloc(argc * sizeof(char *));
556-
fv = (int *)ckalloc(argc * sizeof(int));
557-
if (argv == NULL || fv == NULL) {
590+
if (objc > ARGSZ) {
591+
objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
592+
if (objv == NULL) {
558593
PyErr_NoMemory();
559594
goto finally;
560595
}
561596
}
562597

563-
for (i = 0; i < argc; i++) {
598+
for (i = 0; i < objc; i++) {
564599
PyObject *v = PyTuple_GetItem(args, i);
565-
if (PyTuple_Check(v)) {
566-
fv[i] = 1;
567-
if (!(argv[i] = Merge(v)))
568-
goto finally;
569-
}
570-
else if (v == Py_None) {
571-
argc = i;
572-
break;
573-
}
574-
else {
575-
fv[i] = 0;
576-
argv[i] = AsString(v, tmp);
577-
}
600+
objv[i] = AsObj(v);
601+
if (!objv[i])
602+
goto finally;
603+
Tcl_IncrRefCount(objv[i]);
578604
}
579605
}
580-
/* End code copied from Merge() */
581606

582-
/* All this to avoid a call to Tcl_Merge() and the corresponding call
583-
to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
584-
if (Py_VerboseFlag >= 2) {
585-
for (i = 0; i < argc; i++)
586-
PySys_WriteStderr("%s ", argv[i]);
587-
}
588607
ENTER_TCL
589-
info.proc = NULL;
590-
if (argc < 1 ||
591-
!Tcl_GetCommandInfo(interp, argv[0], &info) ||
592-
info.proc == NULL)
593-
{
594-
char *cmd;
595-
cmd = Tcl_Merge(argc, argv);
596-
i = Tcl_Eval(interp, cmd);
597-
ckfree(cmd);
598-
}
599-
else {
600-
Tcl_ResetResult(interp);
601-
i = (*info.proc)(info.clientData, interp, argc, argv);
602-
}
608+
609+
i = Tcl_EvalObjv(interp, objc, objv, flags);
610+
603611
ENTER_OVERLAP
604-
if (info.proc == NULL && Py_VerboseFlag >= 2)
605-
PySys_WriteStderr("... use TclEval ");
606-
if (i == TCL_ERROR) {
607-
if (Py_VerboseFlag >= 2)
608-
PySys_WriteStderr("... error: '%s'\n",
609-
interp->result);
612+
if (i == TCL_ERROR)
610613
Tkinter_Error(self);
611-
}
612-
else {
613-
if (Py_VerboseFlag >= 2)
614-
PySys_WriteStderr("-> '%s'\n", interp->result);
615-
res = PyString_FromString(interp->result);
616-
}
614+
else
615+
/* We could request the object result here, but doing
616+
so would confuse applications that expect a string. */
617+
res = PyString_FromString(Tcl_GetStringResult(interp));
618+
617619
LEAVE_OVERLAP_TCL
618620

619-
/* Copied from Merge() again */
620621
finally:
621-
for (i = 0; i < argc; i++)
622-
if (fv[i]) {
623-
ckfree(argv[i]);
624-
}
625-
if (argv != argvStore)
626-
ckfree(FREECAST argv);
627-
if (fv != fvStore)
628-
ckfree(FREECAST fv);
629-
630-
Py_DECREF(tmp);
622+
for (i = 0; i < objc; i++)
623+
Tcl_DecrRefCount(objv[i]);
624+
if (objv != objStore)
625+
ckfree(FREECAST objv);
631626
return res;
632627
}
633628

0 commit comments

Comments
 (0)