Just moving ahead now with GTK3

Thanks Brian,

It is complaining about

/mnt/LINWERK/dev/r3n-c/src/include/sys-core.h:133:20: error: conflicting types for ‘dont_include_stdio_h’
133 | #define printf dont_include_stdio_h

(And if I put import <gtk/gtk.h> before import sys-core.h the complaint is about stdio.h)

I know it is not your priority, this is why somebody else must do it. You know I have an interest and it is hard so a great opportunity to learn a lot :slight_smile:

A lot of compilation error still, lots of pointer issues, I confuse *p and p when I declared
Type * p and then think p is the pointer to use in a function argument that wants a Type *, but I figure it out. Learning by repetition.

This is a warning letting you know that something you are including is bringing in a dependency on things like printf(). We like to not build on top of that stuff if we can.

If you're pulling in a file that includes stdio.h and want to ignore that, you can put:


At the top of your file, or wherever before you #include "sys-core.h".

1 Like

That worked! (Of course it did, you said so!)

One really nasty bug I found

 //  export gtk-grid-insert-row : native [

I think I created it when somehow in action at one time the entire : native [
got lost, which was also a real pita to spot.

But at last! The entire thing compiles! So I pushed it (again) to the r3n repo.

Next on the list:

  1. Add the signal connect functions g_signal_connect(), g_signal_connect_swapped() and g_signal_connect_data()
  2. Add many more functions for other widgets.
  3. Test some functions the hard way (without VIEW function)
  4. Create a draft of the VIEW function using some binding examples

So a start was made here, an exiting expedition ahead.

1 Like

I have had a struggle with the connect-signal function, but I won the first battle.
Also added a few TextView and TextBuffer functions now.

I do not yet know how to read in a single character or return it. A character is an issue! type in Ren-C now. It is for the character to be set for masked fields, so for a convenience purpose, not needed right away.

So, with all the examples in the extension it will be a breeze to add other widget types in at a later stage.

Proceeding with the next phase. By now it will be entering Rebol land again.

Time to figure out how to work with all of this and how to store/keep the various widget elements and how to get them updated.

For example a button "Add 1" press leads to the update in another element, say a label element that displays a number, then afterwards the label displays that number plus one.

The way some VIEW implementations, that I have seen till now, work, is iterate over the block collecting items until a new set-word! or widget type is encountered and then construct the desired item.
It is my plan to implement VIEW this way also.

1 Like

Almost forgetting a very important thing here.
Now the extension can be compiled if you add the extension name to the config file.
There has to be a place for some Rebol code to be placed that deals with the functions in the extension, because unlike the MySQL binding where I considered it to be acceptable to deal with this in the user script, this will provide a VIEW like interface.
But if one is to place the code in a mezz source file there must be a way to discard this when there is no GTK extension.

By the way, I looked at the mezz-math.r code and I saw a MATH func there that should take a block!, but when I did that

>> math [2 + 3 * 4]
** Script Error: add does not allow #[datatype! block!] for its value1 argument
** Where: reduce either math console
** Near: [add [[] [] 2] [multiply [[] [] 3] [[] [] 4]] **]
** File: -tmp-boot-
** Line: 7278

Lucky 2 + 3 * 4 still normally returns 20 (you know I consider this better behaviour) :slight_smile:

Need to update the file though to to stay a little actual, must add value for tau.

Started the raw test here.
gtk-init function returns an empty line. Seems to go allright there.

So now assign a window
window: gtk-window-new 0
Segmentation fault (memory dump made) <-- translated message here

And the Rebol Console is exited with that.

Entering thinking mode

Wrong extraction method on my integer! argument.

Code pushed but can do with a cleanup. It is getting late here.


Only had no quit code attached to the Closing-cross, so had to <ctrl>-\ in the console to end it after the window had disappeared.

@hostilefork I need to pass a NULL as an argument to my function

help "NULL"
Found these related words:
NULL void!
null-1? action! Determine if argument would have triggered an...
null-2 action! Make the heavy form of NULL (can't be WORD!-f...
null-2? action! Tells you if the argument is the heavy isotop...
null? action! Tells you if the argument is not a value

help "none"
Found these related words:
none void!

But if I use NULL or none

** Script Error: NULL is ~unset~ (use GET/ANY to GET voids)

** Script Error: none is ~unset~ (use GET/ANY to GET voids)

The g-signal-connect-data function is a tricky thing to implement...

This is due to case-sensitivity, which is still kind of up in the air.

Use null, lowercase.

To get it accepted in types of a function use <opt> in the types, e.g. func [<opt> integer! text!]

Interestingly, those null-2? null-1? things are now done a better way, with the BAD-WORD! ~null~. It's coming together pretty well.

1 Like

Thanks again!

Looks like the start of another breakthrough:

g-signal-connect-data window "destroy" :gtk-main-quit "" 0 0
== 43

43 ???????
shouldn't that be 42 :wink:

And when closing the applicationwindow
Segmentatiefout (geheugendump gemaakt)
(^ Dutch language)
And exits the R3 console back into the terminal session.

Updated some code now and hereby provide the code to play with:

window: gtk-window-new 0
gtk-window-set-title window "Ren-C"
g-signal-connect-data window "destroy" :gtk-main-quit null null 2
box1: gtk-box-new 0 6
gtk-container-add window box1
label1: gtk-label-new "Label!"
button1: gtk-button-new-with-label "Impressive!"
g-signal-connect-data button1 "clicked" :gtk-main-quit null null 0
gtk-container-add box1 label1
gtk-container-add box1 button1
gtk-widget-show-all window

You can press the button and the application closes.
(With the segfault that is)


  1. Solve the segfault issue
  2. Find a way to make it perform Rebol code and not just a C function.
  3. Determine a good place to hold Rebol code for the view function, so it will only be included when the extension is built.
  4. Add the world of gtk functions and rename some to become Rebol friendly.
  5. WD

Point 3 is trivial. It should be inside the ext-EXTENSIONNAME-init.reb
Point 5 is trivial as well, it follow after the new point 5 which is the way opens up to add more similar GUI interfaces for use on systems that do not provide GTK3 natively.

Point 1 I have an idea that it might be helpful to attack this with debug asserts on (I have these turned of atm.) But that could be of no use at all.

Point 2 I had an idea to use the data field in combination with a convenience function that performs the data by use of rebElide of a data block!
(But that can be a bad idea too).

Point 4 anyone can assist to add new functions here. I have a large spreadsheet of available functions.

The segfault was gone for a moment.
But that was not good news, g-signal-connect-data just instantly quit the console at first call :frowning:

Now the segfault is back. Still quitting console here.

Cleaned up again and now the g-signal-connect-data function is returning a result again. Segfault still when exiting "program".

When I look at the old GTK(2) binding that was made for Red versions before 0.4.2 then I notice that the GTK functions are mapped to the Redbol functions through a cdecl interfacing.

We do this binding with some more handcraftingwork, which may be a bit more work but comes with the advantage of being able to do a little steering inside.

Then when the g_signal_connect_data is available as connect-signal and is being invoked, the arguments need to be passed as well. One of the arguments is the callback function. The way this is passed is by using as-integer! :function.

In Ren-C there seems not to be a way to get a handle like that.
Current state is for example TO INTEGER! only supports the ISSUE! type that was formerly known as CHAR! so #"s" thingy's.

You'll need to pass GTK a C function pointer, that uses the rebXXX() routines in its implementation.

Passing a pointer to a Rebol function to C directly requires FFI functionality, which I've removed for now.

I implemented a little helper function I called GET-HANDLE to return a handle! from different kinds of input. So I hope that helps.

It still has some extra debugging prints but basically it is a SUCCESS!!

This is some plain GTK code to enter (just copy and paste into your console)

window: gtk-window-new 0
gtk-window-set-title window "Ren-C"
g-signal-connect-data window "destroy" get-handle :gtk-main-quit window null 2
box1: gtk-box-new 0 6
gtk-container-add window box1
label1: gtk-label-new "Label!"
blok: [print "Hello"]
f: function [][print "Greetings from function f!!!"]
button1: gtk-button-new-with-label "Impressive!"
g-signal-connect-data button1 "clicked" :f null null 0
gtk-container-add box1 label1
gtk-container-add box1 button1
gtk-widget-show-all window
gtk-box-set-homogeneous box1 true
gtk-box-get-homogeneous box1

And it is returning on the button click:

>> gtk-main
Inside self_signal_connect_helper
main level is 1 HIGH
before rebElide of user_data
Greetings from function f!!!
After rebElide of user_data

I must clean up the code, but to preserve working code I just pushed to the r3n branch for you all to reproduce.

Having these things liberates the way to the next level.

I have several code snippets of VIEW and LAYOUT functions laying around so time to decide on how to use GOB!s and what is most efficient for this project.


In the course of all changes that were made to get Ren-C where it is today, how types work has been subject too. The way they used to be in R3-Alpha is incomparable to todays Ren-C source.

So do GOB! type inner working.
If one makes a GOB type

>> gobj: make gob! []
== make custom! [offset: 100.0x100.0 size: 0.0x0.0 alpha: 255]

you note that this is just a small subset of things you can think of that a graphics object needs.

Extending an existing GOB like you would do with an ordinary object does not work.

>> gobj2: make gobj [extra: 1]
** Error: Datatype does not have a MAKE handler registered
** Where: make console
** Near: [*** make gobj [extra: 1] **]
** Line: 1

As this is rather cryptic code that will be taking me a lot of time figuring out, I will now "invent" a new type of object that will be just an object containing the items I will need in the process. The object type will be called a DOB! a Display OBject.
This will do perfectly for now and will be extensible when needed.
>> dob: make object! [offset: 100.0x100.0 size: 0.0x0.0 alpha: 255]
** Syntax Error: invalid "pair" -- ""
** Where: transcode if load trap ext-console-impl entrap console
** Near: (line 1) dob: make object! [offset: 100.0x100.0 size: 0.0x0.0 alpha: 255]
** File: -tmp-boot-
** Line: 5307

Well okay like this :wink:

>> dob: make object! [offset: 100x100 size: 00x0 alpha: 255] 
== make object! [
    offset: 100x100
    size: 0x0
    alpha: 255

and now it can be extended too:

>> dob2: make dob [extra: true]
== make object! [
    offset: 100x100
    size: 0x0
    alpha: 255
    extra: #[true]

There may be many other effects of the made changes that make working with Ren-C a challenge. That is not a bad thing, but where we find similar issues, it is good to think about bringing back a thing or two (not change things back but forward!).

So I had something working, but now the magic combination appears to have gotten lost in the battle.

When I use a debug build with debug: asserts the connect signal function kills the console:

g-signal-connect-data get-handle button1 "clicked" get-handle :f get-handle :f null 0    
r3: /.../r3n-c/src/include/datatypes/sys-handle.h:54: Is_Handle_Cfunc: Controletest 'CELL_KIND(v) == REB_HANDLE' faalt.
Afgebroken (geheugendump gemaakt)

And that is not very helpful, even if I would translate it into English :-/

It is kind of essential that a REN-C function can be passed as or to a CALLBACK function. (GTK needs the CallBack function to be a C function).

You cannot pass a Ren-C function as a callback. C does not know how to call Ren-C functions without the rebXXX() wrapping.

What you can do is create a C function...pass that as a callback, and use the Ren-C API inside the C function.

I feel I have said something in this vein before.

Yes, I had already figured that out, I am now in the process of getting the C function callback do exactly that.
And I had that working too, but I think I had it working with some unsaved code on top of it that I did save to commit a change and now I can't get the working version reconstructed.

(The callbacks are working but passing the function or block and rebElide that does not and is very likely to exit the console)

// Signal helper C
static void self_signal_connect_helper(GtkWidget *widget,
                                       gpointer   user_data){
    rebElide("print {Inside self_signal_connect_helper}");
    rebElide("print {before rebElide of user_data}");
    rebElide("print {After rebElide of user_data}");

And setting this in g-connect-signal-data

result = g_signal_connect_data(instance, detailedsignal, G_CALLBACK(self_signal_connect_helper), chandler, NULL, flags);

Inside self_signal_connect_helper
before rebElide of user_data
Segmentatiefout (geheugendump gemaakt)

Probably need to cast the chandler to the data format, but somehow this was the change that made the thing work (apparently).