From: Lawrence Woodman on
Hello all,

I have been really impressed with TclOO and have moved to using Tcl 8.6.
I am familiar with using the C api to create new procedures, but now want
to create new methods for a class.

The problem I have is that I can't work out how to create a class and set
Tcl_Class for Tcl_NewMethod(). I am using the following code:


#include <tcl8.6/tclOO.h>

/* Mean just returns TCL_OK, for the moment to test and shorten post */
static int Mean(ClientData clientData, Tcl_Interp *interp,
Tcl_ObjectContext objectContext, int objc, Tcl_Obj *const objv[])
{

return TCL_OK;


}

int Mean_Init(Tcl_Interp *interp)
{
Tcl_MethodType meanMethodType;
meanMethodType.name = "mean";
meanMethodType.callProc = Mean;
meanMethodType.deleteProc = NULL;
meanMethodType.cloneProc = NULL;

Tcl_ObjectMetadataType meanClassMetadata;

Tcl_Obj *meanName = Tcl_NewStringObj("mean", 4);


/* How do I set the class, as this is an opaque type and I can
see no functions to set it? */
Tcl_Class className;

Tcl_NewMethod( interp, className, meanName, 1, &meanMethodType,
(ClientData) NULL);

if ( Tcl_PkgProvide(interp, "mean", "0.1") != TCL_OK ) {
return TCL_ERROR;
}

return TCL_OK;
}


I would be very grateful if anyone could point me in the right direction
with this.


Thanks


Lawrence Woodman
From: Donal K. Fellows on
On Jul 17, 7:59 am, Lawrence Woodman <nos...(a)example.com> wrote:
> I have been really impressed with TclOO and have moved to using Tcl 8.6.  
> I am familiar with using the C api to create new procedures, but now want
> to create new methods for a class.
>
> The problem I have is that I can't work out how to create a class and set
> Tcl_Class for Tcl_NewMethod().  I am using the following code:

[cutting to the chase]

> int Mean_Init(Tcl_Interp *interp)
> {
>         Tcl_MethodType meanMethodType;
>         meanMethodType.name = "mean";
>         meanMethodType.callProc = Mean;
>         meanMethodType.deleteProc = NULL;
>         meanMethodType.cloneProc = NULL;

The method type structure isn't copied and is assumed to be constant;
make it static to your extension.

>         Tcl_ObjectMetadataType meanClassMetadata;
>
>         Tcl_Obj *meanName = Tcl_NewStringObj("mean", 4);
>
>         /* How do I set the class, as this is an opaque type and I can
> see no functions to set it? */
>         Tcl_Class className;

All TclOO classes are objects. Look them up with Tcl_GetObjectFromObj
(or create with Tcl_NewObjectInstance applied to the class of classes)
and then use Tcl_GetObjectAsClass to get the class interpretation (if
it's NULL, it's not a class).

>         Tcl_NewMethod( interp, className, meanName, 1, &meanMethodType,
> (ClientData) NULL);

You're recommended to use Tcl_IncrRefCount and Tcl_DecrRefCount on
meanName on either side of that call. That's because the name *may* be
retained (probably will if you're dealing with a clean class, but not
if something with the same name is there already; play it safe as it
is easy. :-))

> I would be very grateful if anyone could point me in the right direction
> with this.

I hope this is enough.

Donal.
From: Lawrence Woodman on
Donal,

On Sat, 17 Jul 2010 01:39:38 -0700, Donal K. Fellows wrote:

> [cut]
>
> All TclOO classes are objects. Look them up with Tcl_GetObjectFromObj
> (or create with Tcl_NewObjectInstance applied to the class of classes)
> and then use Tcl_GetObjectAsClass to get the class interpretation (if
> it's NULL, it's not a class).
>
>>         Tcl_NewMethod( interp, className, meanName, 1,
>>         &meanMethodType,
>> (ClientData) NULL);

Thanks for your help, it is all working now. I got a bit confused because
of the way that Tcl_NewObjectInstance works and didn't expect to have to
create a new object instance, but on reflection I can see the logic to
how this.

> You're recommended to use Tcl_IncrRefCount and Tcl_DecrRefCount on
> meanName on either side of that call. That's because the name *may* be
> retained (probably will if you're dealing with a clean class, but not if
> something with the same name is there already; play it safe as it is
> easy. :-))

Ah yes, I had missed this with all my experimenting.


Best wishes


Lawrence Woodman