Next: , Previous: Kite Language Specification, Up: Top


4 Extending Kite

There are two ways to extend Kite: write your own classes/packages and writing your own compiled extensions.

4.1 Kite Packages

To write a package, it is a simple matter of saving your classes and other code in a file with the .kt extension. For example, here is a simple package:

     #!/usr/bin/kite
     
     class Greeting [
         property text,
         method sayGreeting() [
             text|print;
         ]
     ];
     
     class Hello from Greeting [
         construct [
             this.text = "Hello!";
         ]
     ];
     
     class Hola from Greeting [
         construct [
             this.text = "¡Hola!";
         ]
     ];

We shall call this Greetings.kt. Now, where should this be placed? We know that greetings fall under common sayings, so let's place this in the CommonSayings folder. Now, the package can be referenced by using import CommonSayings.Greetings in any Kite application. Let's try it:

     #!/usr/bin/kite
     
     import "CommonSayings.Greetings";
     greetings = CommonSayings.Greetings;
     
     english = make greetings.Hello;
     spanish = make greetings.Hola;
     
     english|sayGreeting;
     spanish|sayGreeting;

Assuming that your folder structure looks like this:

     ./CommonSayings/
     ./CommonSayings/Greetings.kt
     ./test.kt

Running kite test.kt will produce:

     Hello!
     ¡Hola!

Easy enough, but what if your package isn't in the current Kite search path? You'll have to use something like this to fix that:

     #!/usr/bin/kite
     
     import "System.vm.loader";
     System.vm.loader.searchPath = System.vm.loader.searchPath + ":/path/to/package";
     greetings = System.vm.loader|loadClass("CommonSayings.Greetings");
     
     english = make greetings.Hello;
     spanish = make greetings.Hola;
     
     english|sayGreeting;
     spanish|sayGreeting;

Now, it'll work as intended.

Caution: import will only load a class once during runtime. If you need to reload the package for any reason, you'll currently need to restart Kite. (This is on the TODO for future releases.)

4.2 Compiled Extensions

Compiled extensions are the second route to extending Kite. There are two routes to doing this: native extensions and using the interface.language.c class.

4.2.1 Native Kite extensions

Right now, this method isn't well documented, but you can see how to write one by looking at modules/System/string.c in the Kite distribution. The loading process is similar to packages written in Kite, but the difference is the extension is a shared library object, usually compiled by gcc using something like the following:

     gcc -shared -o library.so file1.c file2.c ...

If you have Doxygen, you can generate documentation for all of the Kite internals by running doxygen Doxyfile from the top of the distribution. It should place HTML and LaTeX files in docs/html and docs/latex, respectively.

4.2.2 Using interface.language.c

Note: This method only works on platforms supported by C/Invoke. At this writing (July 2008), the supported platforms are Windows (32-bit Intel), OS X (PPC and Intel) and Linux/*BSD (32 and 64-bit Intel).

interface.language.c is a module that allows one to interface with compiled modules on his or her system. No experience with C/C++ or Kite internals is necessary.

Here is a simple example of using interface.language.c:

     import "interface.language.c";
     
     libr = make interface.language.c("libm.dylib");
     libr|add_method(
     	"cos",
     	interface.language.c.param_types.double,
     	[interface.language.c.param_types.double]
     );
     libr|cos(0.0)|print;

(the example prints "1.00000")

Structures and callback functions are also supported. Here is a longer example that implements both. First, we'll create a quick and simple dynamic library called libtest. Here are the contents of libtest.c:

     #include <stdio.h>
     
     struct xyz
     {
         char *name;
         int val;
     };
     
     void print(struct xyz *ptr, int x, void(*ptr)(int))
     {
         printf("name = %s, value = %d\n", ptr->name, ptr->val);
         (*ptr)(x);
     }

To compile on Linux: gcc -shared -g -o libtest.so libtest.c. Now here is the Kite code necessary to access our new module:

     import "interface.language.c";
     
     lib = make interface.language.c("/tmp/libtest.so");
     
     st = make interface.language.c.c_struct(
     	lib,
     	[
     		["name", interface.language.c.param_types.string],
     		["val", interface.language.c.param_types.int]
     	]
     );
     
     inst = st|make_instance;
     inst|name("test");
     inst|val(123);
     
     cb = make interface.language.c.c_callback(
         lib,
         interface.language.c.param_types.void,
         [interface.language.c.param_types.int],
         method(extra, x) [
             x|print;
         ],
         null
     );
     
     lib|add_method(
     	"print",
     	interface.language.c.param_types.void,
     	[
     	    interface.language.c.param_types.pointer,
     	    interface.language.c.param_types.int,
     	    interface.language.c.param_types.pointer
     	]
     );
     
     lib|print(inst|pointer, 31415, cb|pointer);

This results in:

     name = test, value = 123
     31415

More information on interface.language.c can be found in the kdoc documentation for the current version.