robertmuench.de

To the point & Out of the box


Rebol-3 Extensions

Rebol-3 is still Alpha, but it is already pretty good. The GUI part is not useable yet but the command line version alone gives a lot.

Rebol-3 is still Alpha, but it is already pretty good. The GUI part is not useable yet but the command line version alone gives a lot.

One thing that was really a PITA in Rebol-2 was the external DLL interface. The interface you have to use to call C code functions. This interface was totally reworked in Rebol-3. After it stabilized a bit I gave it a try and ported some Rebol-2 interface code to Rebol-3.

The C level code could mostly stay the same. The only thing that I had to add was the Rebol-3 interface code. This code is pretty straight forward. The tricky part is in dealing with Rebol parameters and return values. The parameters a bit tricky because Rebol-3 uses Unicode internally. So you can’t just use a char* for example. You need to convert to a char*.

This is a two step process:
  1. You need to access the string at all. A Rebol-3 string is a series datatype. So you use the RXA_SERIES macro to access the series.
  2. After this you use RXI_GET_STRING to get back a char*

The hard part is to construct the return values. If you just return simple datatypes like INTEGER! it’s pretty simple. But constructing a nested block is tricky. I have scribbled down the structure I want to return. And, what you need to remember is, that a STRING! is a series too. Seems obvious but it adds one more nested level.

If you want to use a BLOCK to insert into an other BLOCK, you need to wrap the to-be-insert-block into a RXIARG structure. This is necessary because a BLOCK consists of a pointer to the series and an index position.

RXIARG rec;
REBSER *s = 0;
rec.ser.index = 0;
rec.ser.series = s = RXI_MAKE_BLOCK(columns);

Now you can use ’s’ to work with the BLOCK itself, and ‘rec’ if you want to use the BLOCK as parameter for some other macros.

Another thing to keep in mind is that all Rebol values are handled through a C union. Depending on the type handled other fields of the union are used. This shows when you want to traverse a BLOCK from the C level. Because a BLOCK can contain any datatype you don’t know what you will get if you just access the BLOCK data. The RXI_GET_VALUE macro is used for this. It returns the type of the value you accessed. That was something I overlooked at first and wondered how to find out what kind of value I have. You can easily use a switch based on the returned type to handle all datatypes.
0 Comments