- C 66%
- Makefile 33.4%
- Shell 0.6%
| example2d | update readme | |
| example3d | update readme | |
| external | added fixed make file, user no longer needs to install k independently | |
| .gitignore | raylib runs | |
| camera.k | update readme | |
| colors.k | forgot to add these files | |
| ffi.k | update readme | |
| input.k | update readme | |
| libffi.c | add explanations | |
| LICENSE | added license as required per AGPL usage of ngn/k | |
| main.k | update readme | |
| makefile | update readme | |
| project.k | add explanations | |
| README.md | readme | |
| run | update readme | |
KFFI Example
- clone
- checkout raylib
- make
- read post script in
main.kto learn more
Purpose
This project illustrates successful linking, compiling, and execution of external c libraries from ngn/k.
This repository is for instructional and illustrative purposes, and may be used and transformed by anyone for any reason.
Examples
The following 2 raylib examples were ported for illustration purposes. Example3D is selected in main.k by default
Example 2D
Example 3D
Instructions
$ make
If there are any errors, you can start over with make clean, then make again
make clones, links and compiles all libraries.
./run will run the program without triggering the compilation step.
When the C library in libffi.c is modified, run make libffi.so
$ make # link and compile all things
$ make clean # get rid of anything not in the git repo
$ ./run # run main.k without the compilation step
$ make libffi.so # build only changes from libffi.c, then simply use ./run again
Comments in ./makefile are illustrative to anyone wishing to understand how to link libraries.
Explanation
Why this architecture
This project contains the following files:
./project.k # describes library interface and include statements
./example3d # k code porting raylib 3d example
./example2d # k code porting raylib 2d example
./external # a directory storing some external library source code
./makefile # describes how to build the project and dependencies
./main.k # entry point to the primary k program
./run # script to run the main k program without the build step
./ffi.k # load library functions (from main) and generate c code
But core files the user should expect to modify are limited to the following:
./project.k # describes library interface and include statements
./main.k # entry point to the primary k program
./makefile # link your external libraries in the libffi.so step
Since the ngn/k ffi only works with k-values, it is necessary to wrap any call to external C code by first converting the k-values to c-values.
The interface for this is provided in ngn/k/k.c
For atomic conversions, the convention of a lower-case letter is used. For list conversions, upper cased naming convention is used.
char cK(K); // convert from k-char to c-char
K Kc(char); // convert from c-char to k-char
int iK(K); // convert from k-int to c-int
K Ki(int); // convert from c-int to k-int
K Ks(char *); // convert from c-string to k-string
K Kf(double); // convert from c-double to k-double
double fK(K); // convert from k-double to c-double
With this FFI, a simple call to an addition function would look like this:
#include<stddef.h>#include<k.h>K add(K x,K y){
int a = iK(x); // convert from k-int to c-int
int b = iK(y);
return Ki(a + b); // return the value a+b as a k-int
}
The goal of this project was to require a user to edit as few files necessary to generate this middleware easily and without fuss.
To that end, ./project.k describes the C library interface, which is imported by ./ffi.k, while ./main.k is the application entry point.
./project.k # define imports
./ffi.k # do importing
./main # entry point which calls example3d/main.k
How to import libraries
The ./project.k should define 2 variables: includes and lib.
These are important, since the ./ffi.k does important argument parsing before being passed to C functions.
Any additions or subtractions to ./libffi.c should be preceeded by adding/removing those functions in ./project.k
Any changes to ./libffi.c should be followed by make libffi.so
Any new libraries you wish to add, flags adding those libraries must be added to the libffi.so step in the ./makefile
- place
lib<libname>.sofiles in./obj - include headers in
./project.k - add
-l<libname>compiler flags to thelibffi.so:$(FILE)step in./makefile
lib (./project.k)
includes is a list of lists, each containing (function name;argument types;return type)
lib:((`plus ;`int`int;`int)
(`minus ;`int`int;`int)
(`mulx ;`int`int;`int)
(`intdiv ;`int`int;`int))
Attributions
Thanks to @ktye @DiscoDoug @rak1507 @mlochbaum in the APLFarm discord for information regarding existing functionality, for the existing writeups about the ffi, for work designing and exposing the K internals so that an FFI is possible at all, and help debugging the object code so I could successfully link external libraries at all.