1

In writing a C extension for Rebol3, I need to pass to Rebol a pointer to an object I got from a native function.

  1. The documentation says that there is a special datatype: "handle: A way to store code and data pointers". But I would like an example!

  2. I want to call a native destructor when this handle is unbound. Is there a way to do this?

giuliolunati
  • 766
  • 5
  • 14

1 Answers1

2

To store a pointer as a Rebol handle you can do something like this:

RXIARG value;
value.addr = original_pointer;
RL_SET_FIELD ( obj, RL_MAP_WORD ( (REBYTE *) "handle-attribute" ), value, RXT_HANDLE );

In this example I'm setting the handle-attribute attribute of the obj object to the value of original_pointer

Later you can retrieve the value of the handle like this:

int dtype = 0;
RXIARG value;

dtype = RL_GET_FIELD ( obj, RL_MAP_WORD ( (REBYTE *) "handle-attribute" ), &value );

switch ( dtype ) {
  case RXT_NONE:
    printf ( "Invalid handle: none\n" );
    break;

  case RXT_HANDLE:
    original_pointer = value.addr;
    break;

  default:
    printf ( "Invalid handle: none\n" );
}

I usually use objects to store handles into, so the obj object in the example can be retrieved from Rebol command frame this way:

REBSER *obj;
obj = RXA_OBJECT ( frm, 1 );

where frm is Rebol command frame and 1 is the position of the object in the parameter list passed to your command.

If you want to use blocks to store handles the macros to use to store/retrieve a value from a block are RL_SET_VALUE and RL_GET_VALUE in place of RL_*_FIELD, but the part where you copy your pointer to value.addr doesn't change.

You can also return a handle as a result of calling an extension's command by ending the command with the following instructions:

RXA_HANDLE ( frm, 1 ) = original_pointer;
RXA_TYPE ( frm, 1 ) = RXT_HANDLE;
return RXR_VALUE;

As far as your second question is concerned I think that by now there's no way to know when the handle is unbound or gets garbage collected to trigger a native destructor.

kronwiz
  • 193
  • 7