So,
I finally got around to doing a bit of #coding in #genie tonight. Nothing spectacular, but I would like to log what I am doing for those who may also be curious to learn how to code in Genie, in particular how you work with #GLib, the namespace of which is not yet in human-only-readable form yet for how you use it in #Vala or Genie.
The thing I figured out is that you can read it directly in the .vapi files, I published a link to a repository of non-official ones, and the official ones get installed in
/usr/share/vala-0.30/vapi/
In these files, written in Vala, which has a nearly 1:1 correspondence with Genie except in some things - Genie mainly just dispenses with squiggly brackets, every other element has an equivalent.
In the main tutorial about Genie, it explains the naming conventions, and with these in hand I was quickly able to work out what I should be doing. My examples show them so you don't have to figure them out. Once you know how they tend to map to each other, and poke around in the vapi files, you will more quickly be able to know how what the C-language GLib documentation shows you.
Also things like that in the C version, the methods associated with GLib objects have a variable parameter which is the object itself. This is not needed in an OOP language because it is explicitly stated, objectname.methodname() means methodname(*objectname), more or less, this is the binding between objects and methods.
In this code I wrote this evening, there is an example of a closure, which is the statement where you see:
+= def (t,a)
The code that follows in the next indent level after this is a callback function that runs when the event occurs, in this case called 'incoming'. I am not precisely sure what the t and a contain, but I know that one is a list of references to data fed back from an event source, such as a light level or user input, or in this case, data arriving at a TCP port.
To the codecave, batman!
The following code takes a single parameter from the commandline, which it checks is a number between 1024 and 65535 (the range of unprivileged ports on a TCP connection), then it creates a listener, starts the GLib event loop (MainLoop), and as far as I have got with testing it is to probe it with telnet, which pings it and disconnects because it doesn't get a handshake (but this program recognises it received a connection and was sent data).
[indent = 2]
init
var mainloop = new MainLoop
var maincontext = new MainContext
var portnumber = int.parse(args[1])
if portnumber < 1024 or portnumber > 65535
print "Port number must be between 1024 and 65535"
return
var subchain_socket = new SocketService
try
subchain_socket.add_inet_port ((uint16) portnumber, null)
except ex : Error
print "Unable to open port no. " + portnumber.to_string()
print "Opened port no. " + portnumber.to_string()
print "Data received on port will be output to the terminal. Press enter to end."
subchain_socket.incoming += def (t,a)
print "characters coming from remote source"
return true
subchain_socket.start()
mainloop.run()
To compile this, the following script is what I use. The main prerequisite for being able to do all this is to install valac, the vala compiler suite. If you are also doing Gtk, there is some other requirements.
#!/bin/bash
valac \
src/main.gs \
--pkg gio-2.0 \
--output agora
This lists all the source files that go together (only one can have the init block), it allows you to access the IO management system in gio,-2.0 this provides files, virtual filesystems and network access methods, and sets the filename of the executable after --output
I have been trying to figure out an auto-configure for a "proper" source package but they all don't know that .gs files are for valac. I will dig that one up eventually.
Note that the test that ensures that the port number used by the program is within the correct range is called 'data sanitisation'. I think it should be a subject in computer programming, called 'hygiene'. Things like trusting users not to put rubbish in and maybe in an attempt to squeeze some h4x into your stack and have it able to compromise your system... Well written functions that may possibly receive bogus data should always check the data, and either reject it or strip out the rubbish.
Next up:
I will write a second piece of code that opens a connection to our first program and find out how to get it to write the input to the console that you put in from the other side.
Note
I know that this is horribly unmodular and hackish code, but it is a very short procedure it is implementing. Once I have this working, I will create an initialisation function that is called from the main (the block under 'init') and the callback will actually do something with that data like have a conversation with the caller. Probably I will start creating a class to bundle its functions together.
It can be a good idea to comment out or leave unused functions in your code when you are learning, so you can look at it to remember the syntax for some function or other you learned how to use so you don't have to dig through cryptic manuals again.
Happy Coding!
We can't code here! This is Whale country!
Written with StackEdit.