roxen.lists.pike.general

Subject Author Date
Re: cmod inherit question Johan Björklund <Johan Björklund[at]nirgendwo> 10-11-2009
A few things. The best way to know what CMOD does is to examine the 
generated .c file and find the macros generated there.

The "THIS" macro is defined within each PIKECLASS block to cast the 
storage-pointer of the "this" object to the struct defining the member 
variables. That is why you can use -> references in c.

However, on the c-level, all object-type PIKEVARs are defined struct 
*object.

> And want to use it in the next class:
>
> PIKECLASS Control {
>     INHERIT HostApiInfo;
>     PIKEVAR HostApiInfo Info;
This does work, and will be a struct *object. To access members in this 
object from within this class, you must use the OBJ2_HOSTAPIINFO macro, 
which casts an object into the struct you want.
>     PIKEFUN HostApiInfo get_host_api_info(int hostApi) {
>         const PaHostApiInfo * info;
>         info = Pa_GetHostApiInfo(hostApi);
>         THIS->Info->structVersion = info->structVersion;
This should be OBJ2_HOSTAPINFO(THIS->Info)->structVersion = 
info->structVersion.
>         [...]
>         RETURN(THIS->Info);
>     }

> But it doesn't work that way. At least the HostApiInfo class was 
> recognised as a PIKEVAR, but when i use the structVersion function the 
> compiler complains:
>
>     error: ‘struct object’ has no member named ‘structVersion’
>
> I know, the structure is not initialized. But where and how to do 
> that? I tried something like
>    THIS->Info = HostApiInfo();
This would be:

THIS->Info = low_clone(HostApiInfo_program);
call_c_initalizers(THIS->Info);

But because of INHERIT pike will make a new HostApiInfo object 
automatically everytime a new Control object is made. The way to access 
it is to use the get_storage(struct object*, struct program*) function.

Try something like this:

#define THISOBJ Pike_fp->current_object;

PIKECLASS HostApiInfo {
  /* ... */
}

#define SUPER_HOSTAPIINFO(o) ( ((struct HostApiInfo_struct *) 
get_storage((o), HostApiInfo_program)) )

PIKECLASS Control {
  INHERIT HostApiInfo;

  PIKEFUN int set_version(int version) {
    RETURN (SUPER_HOSTAPIINFO(THISOBJ)->structVersion = version);
  }
}

(I might have missed a bracket or two and it be slightly wrong but the 
that's the basics)

When you use reference types such as objects and strings in CMOD, you 
must initalize them, otherwise they will blow up in pike:

PIKECLASS HostApiInfo {
    PIKEVAR string name;
  
    INIT{
      THIS->name = NULL;
    }
   
    EXIT{
      if (THIS->name != NULL) free_string(THIS->name);
    }
}

You should use a pike compiled with the "--with-checker" option. 
Otherwise you won't see your memory problems.