Accessing variables in a class object from within a CMOD?

View: New views
20 Messages — Rating Filter:   Alert me  

Accessing variables in a class object from within a CMOD?

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Suppose I have a cmod function:

  PIKEFUN array decodedatarow(int msglen, object portal) {
    ...
  }

Which is called as:

class portal {
  int a;
  int b;
};

  portal abc=portal();

  decodedatarow(12, abc);


How would I access the svalues of the members a and b from within the
cmod function decodedatarow() ?
--
Sincerely,
           Stephen R. van den Berg.

"Well, if we're going to make a party of it, let's nibble Nobby's nuts!"

Accessing variables in a class object from within a CMOD?

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

struct svalue a, b;
object_index_no_free(&a, portal, 0, MK_STRING_SVALUE("a"));
object_index_no_free(&b, portal, 0, MK_STRING_SVALUE("b"))

Accessing variables in a class object from within a CMOD?

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

And to set them:

object_set_index(portal, 0, MK_STRING_SVALUE("a"), &a);
object_set_index(portal, 0, MK_STRING_SVALUE("b"), &b);

Re: Accessing variables in a class object from within a CMOD?

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Stephen R. van den Berg wrote:
>  PIKEFUN array decodedatarow(int msglen, object portal) {

>class portal {
>  int a;
>  int b;
>};

After digging through the Pike sources, the best I can come up with
is something like:

safe_apply(portal,"a",0);

But that doesn't seem right, and it also doesn't tell me how to handle
things like:
      portal->a += 7;
from within the cmod function.

I get the impression that in none of the existing C(MOD)-modules this is
attempted (I see lots of calls to methods of other classes, but no
references to variables), so I'm missing an example here.
--
Sincerely,
           Stephen R. van den Berg.

"Well, if we're going to make a party of it, let's nibble Nobby's nuts!"

Re: Accessing variables in a class object from within a CMOD?

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum wrote:
>And to set them:

>object_set_index(portal, 0, MK_STRING_SVALUE("a"), &a);
>object_set_index(portal, 0, MK_STRING_SVALUE("b"), &b);

Thanks.
That got me on the right track.
--
Sincerely,
           Stephen R. van den Berg.

"Well, if we're going to make a party of it, let's nibble Nobby's nuts!"

Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

One more question:

When doing the following:

  Pike_sp++;
  object_index_no_free2(Pike_sp-1, portal, 0, MK_STRING_SVALUE("_total"));

What am I supposed to do to cleanup after using the returned svalue?

  Pike_sp--;
or
  pop_stack();

?

And, on a related note, what if I do:

  Pike_sp++;
  object_index_no_free2(Pike_sp-1, portal, 0, MK_STRING_SVALUE("_total"));
  ... some processing ...
  object_set_index2(portal,0, MK_STRING_SVALUE("_total"), Pike_sp-1);

What do I need at this point, Pike_sp-- or pop_stack() ?

In the above examples the values of _total could have been arrays or
ints or strings; I presume the answers are the same regardless of the
datatype.
--
Sincerely,
           Stephen R. van den Berg.

"Well, if we're going to make a party of it, let's nibble Nobby's nuts!"

Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

object_index_no_free*() will add a reference for the item on the
stack, so you need to free the svalue afterwards, which is
conveniently done by pop_stack().  There is no difference between your
two snippets; object_index_no_free*() adds a ref, so you need to
subtract it when you're done.

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum wrote:
>object_index_no_free*() will add a reference for the item on the
>stack, so you need to free the svalue afterwards, which is
>conveniently done by pop_stack().  There is no difference between your
>two snippets; object_index_no_free*() adds a ref, so you need to
>subtract it when you're done.

So how do I do an efficient:

   class A {
     array b;
   };

   A c=A();
...
  then from with the CMOD:

   c->b+=({12});

I would like the += code to destructively expand array b, which would be
possible if it had only one reference.
But object_index_no_free adds a reference, you say.  So how do I solve
this?

I use this:
    push_int(12);
    f_aggregate(1);
    Pike_sp++;
    object_index_no_free2(Pike_sp-1, portal,0, MK_STRING_SVALUE("_datarows"));
    stack_swap();
    f_add(2);
    object_set_index2(portal,0, MK_STRING_SVALUE("_datarows"), Pike_sp-1);
    Pike_sp--;

I realise that I need to run pop_stack() at the end instead, but that
still leaves me puzzled about the efficient append.
--
Sincerely,
           Stephen R. van den Berg.

"Well, if we're going to make a party of it, let's nibble Nobby's nuts!"

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The reference to the old array on the stack is removed by f_add().  So
the extra reference you should be worried about is the one in
_datarows.  Because as long as the variable in the object holds a
reference to the old array, it can not be destructively modified.
I expect setting _datarows to 0 after the index_no_free2() but before
the f_add() should do the trick, but maybe there is a more elegant
solution?

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum wrote:
>object_index_no_free*() will add a reference for the item on the
>stack, so you need to free the svalue afterwards, which is

Incidentally, what does the "no_free" in object_index_no_free() refer to
then?
That the target svalue is not freed before overwriting?
That the source svalue is not freed, but normally it would have been?
And if the latter, then how is that supposed to work, since it wouldn't
make much sense to extract the value from the class and then
automatically delete it, or?
--
Sincerely,
           Stephen R. van den Berg.

"Well, if we're going to make a party of it, let's nibble Nobby's nuts!"

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

>Incidentally, what does the "no_free" in object_index_no_free() refer to
>then?
>That the target svalue is not freed before overwriting?

Exactly.  So it is the correct version to use when the svalue you are
overwriting is not initialized (uninitialized C variable, new stack
entry etc).

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum wrote:
>The reference to the old array on the stack is removed by f_add().  So
>the extra reference you should be worried about is the one in
>_datarows.  Because as long as the variable in the object holds a
>reference to the old array, it can not be destructively modified.
>I expect setting _datarows to 0 after the index_no_free2() but before
>the f_add() should do the trick, but maybe there is a more elegant
>solution?

Well, I went with this:

    f_aggregate(nrows);
    Pike_sp++;
    object_index_no_free2(Pike_sp-1, portal,0, MK_STRING_SVALUE("_datarows"));
    if(Pike_sp[-1].u.array->size) {
      push_undefined();
      object_set_index2(portal,0, MK_STRING_SVALUE("_datarows"), Pike_sp-1);
      pop_stack();
      stack_swap();
      f_add(2);
    }
    else
      pop_stack();
    object_set_index2(portal,0, MK_STRING_SVALUE("_datarows"), Pike_sp-1);
    pop_stack();

Because, as it turns out, in most cases, the array is empty before we
start.
--
Sincerely,
           Stephen R. van den Berg.

"Well, if we're going to make a party of it, let's nibble Nobby's nuts!"

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

You should check that the value actually is an array before accessing
.u.array.  Otherwise it looks ok.

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

>Well, I went with this:
>
>    Pike_sp++;
>    object_index_no_free2(Pike_sp-1, portal,0, MK_STRING_SVALUE("_datarows"));

For error throwing consistency reasons, it's better to swap the above
two lines; eg:

|    object_index_no_free2(Pike_sp, portal,0, MK_STRING_SVALUE("_datarows"));
|    Pike_sp++;

Otherwise, the error cleanup code will pop an uninitialized stack
value in case object_index_no_free() throws an error.

>--
>Sincerely,
>           Stephen R. van den Berg.

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hm, if you work on the stack anyway, wouldn't it be easier to push
what you want indexed, push_text("something") and call f_index(2)?

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Mirar @ Pike  developers forum wrote:
>Hm, if you work on the stack anyway, wouldn't it be easier to push
>what you want indexed, push_text("something") and call f_index(2)?

If that can handle an object/class pointer in 'portal', and then dereference
it using a pikestring or svalue-string, yes.

It's not immediately clear that this works, since it is not documented
anywhere, I learn mostly by grepping for sample code that does/did the
same in the Pike repository.
--
Sincerely,
           Stephen R. van den Berg.

"Very funny, Mr. Scott. Now beam down my clothes!"

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Well, it would do exactly the same thing as would happen in Pike
itself.

push_object(obj);
push_text("something");
f_index(2);

<->

obj->something;

(or rather obj["something"] iirc. f_arrow() for ->-indexing.)

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Mirar @ Pike  developers forum wrote:
>Well, it would do exactly the same thing as would happen in Pike
>itself.

>push_object(obj);
>push_text("something");
>f_index(2);

I went with something like:

    ref_push_object(portal); ref_push_string(MK_STRING("_datarowdesc"));
    f_arrow(2); datarowdesc=Pike_sp[-1].u.array;
    pop_stack();

And about type checking, the helper class knows that the types are
filled correctly before it's being called.  I only need to account for
bad user input/database behaviour.

Incidentally, it's these silly things like, when to use push_string or
when to use ref_push_string and the same for push_object vs.
ref_push_object which take time to figure out.
--
Sincerely,
           Stephen R. van den Berg.

"Very funny, Mr. Scott. Now beam down my clothes!"

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Martin Stjernholm, Roxen IS @ Pike developers forum :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 >    ref_push_string(MK_STRING("_datarowdesc"));

That's more or less what push_text does. I think. Possibly MK_STRING
is better optimized via cmod? push_text seems to recreate the shared
pointer every time.

 >    f_arrow(2);
 >    datarowdesc=Pike_sp[-1].u.array;
 >    pop_stack();

Possibly you either want to increase the reference counter of the
array, or use Pike_sp--; instead of pop. (But maybe you do that
already, or cmod does it magically for you?)

 >Incidentally, it's these silly things like, when to use push_string or
 >when to use ref_push_string and the same for push_object vs.
 >ref_push_object which take time to figure out.

Yes. :p

Re: Pike_sp-- vs. pop_stack() (Re: Accessing variables in a class object from within a CMOD?)

by Stephen R. van den Berg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Mirar @ Pike  developers forum wrote:
> >    ref_push_string(MK_STRING("_datarowdesc"));

>That's more or less what push_text does. I think. Possibly MK_STRING
>is better optimized via cmod? push_text seems to recreate the shared
>pointer every time.

MK_STRING does something very clever and rather optimal.

> >    f_arrow(2);
> >    datarowdesc=Pike_sp[-1].u.array;
> >    pop_stack();

>Possibly you either want to increase the reference counter of the
>array, or use Pike_sp--; instead of pop. (But maybe you do that
>already, or cmod does it magically for you?)

Good point.  No, it doesn't happen, then again, program logic dictates
that nobody is messing with that array, the only thing that could mess
this up is an unexpected destruction of this object.  I'll ponder it
some more and see if this safeguard is necessary (and where I need it as
well, because I use this construct on three or four items).

> >Incidentally, it's these silly things like, when to use push_string or
> >when to use ref_push_string and the same for push_object vs.
> >ref_push_object which take time to figure out.

>Yes. :p

And the coredumps that follow don't really give enough clues.
--
Sincerely,
           Stephen R. van den Berg.

"Very funny, Mr. Scott. Now beam down my clothes!"
LightInTheBox - Buy quality products at wholesale price!