Skip to content

Commit 90bd3ec

Browse files
committed
Added README with C.scala documentation
1 parent 1ee3a94 commit 90bd3ec

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

README.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
C.scala: A Shallow DSL for C
2+
============================
3+
4+
This project defines a Scala library for the core C language and some useful C
5+
libraries. It also provides implementations of Scala collections such as HashMap
6+
or List in the C DSL.
7+
8+
Installation
9+
------------
10+
11+
The shallow C definitions are accompanied by implementations which use the JNI.
12+
`sbt compile` will take care of generating and compiling the required C code,
13+
provided that:
14+
15+
* GLib is installed on your system. You can check this by making sure that
16+
`pkg-config --list-all | grep glib` prints something.
17+
18+
* clang is installed on your system (`which clang` should not return an error).
19+
20+
* The JNI headers for your system are as specified in `project/Build.scala`.
21+
22+
23+
The core C language
24+
-------------------
25+
26+
The functionality of the C language itself is provided in the `cscala.CLang` package.
27+
This includes functions such as `sizeof`, address-taking and dereferencing.
28+
29+
This functionality is contained in the `cscala.CLang` package. The following import
30+
is also needed in order to use it:
31+
32+
```scala
33+
import cscala.CLangTypes._
34+
```
35+
36+
To use the JNI implementations, the calling code needs to load the library
37+
generated during compilation:
38+
39+
```scala
40+
System.loadLibrary("shallow")
41+
```
42+
43+
### Pointers
44+
45+
C.scala deals with pointers by providing the Scala type `Pointer[T]`. Pointers
46+
to values can be obtained using the `&` method and those pointers can be
47+
dereferenced using the `*` method:
48+
49+
```scala
50+
val x: Int = 5
51+
val px: Pointer[Int] = &(x)
52+
println(*(x))
53+
// => 5
54+
```
55+
56+
Note: currently, calling `&` on the same value twice will return pointers to
57+
different copies of the value.
58+
59+
It is possible to perform pointer arithmetic using the `pointer_add` and
60+
`pointer_sub` methods. Assignment is possible using `pointer_assign`. For
61+
example, using `malloc` from the `cscala.StdLib` pacakge it is possible to write
62+
array-like operations:
63+
64+
```scala
65+
val array: Pointer[Int] = malloc[Int](5) // Allocates space for 5 integers
66+
for (i <- 0 until 5) {
67+
pointer_assign(pointer_add(array, i), i)
68+
}
69+
70+
println(*(pointer_add(array, 3)))
71+
// => 3
72+
```
73+
74+
### Structs
75+
76+
It is possible to declare and use structs with C.scala, but declaration is
77+
currently cumbersome. A struct is declared by declaring both a subclass of
78+
`CStruct` and an instance of `CStructInfo[T]` for your new struct `T`. For
79+
example:
80+
81+
```scala
82+
class CTimeVal(val bytes: Array[Byte]) extends CStruct {
83+
def this(sec: Long, usec: Long) =
84+
this(ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN).putLong(sec).putLong(usec).array)
85+
}
86+
implicit val CTimeValInfo: CStructInfo[CTimeVal] = new CStructInfo[CTimeVal] {
87+
val sizes = List(
88+
'tv_sec -> sizeof[Long],
89+
'tv_usec -> sizeof[Long])
90+
def create(bytes: Array[Byte]) = new CTimeVal(bytes)
91+
}
92+
```
93+
94+
Structs can be created using `malloc`, `pointer_assign` and `pointer_add`, or by
95+
simply creating a new instance of the `CStruct`. Member selection in pointers to
96+
structs can be done using the `->` method:
97+
98+
```scala
99+
val tv = new CTimeVal(12 ,45)
100+
val p = &(tv)
101+
println(->[CTimeVal, Long](p, 'tv_sec))
102+
// => 12
103+
```
104+
105+
### Casts
106+
107+
C programmers expect to be able to cast between types without runtime errors.
108+
Since Scala casts will fail at runtime when attempting, for example, a cast from
109+
a `Pointer[Int]` to a `Int`, C.scala provides an alternative way to cast via
110+
the `as` method. `as[Int](p: Pointer[Int])` will cast the pointer to an int
111+
(the underlying address pointed to) without failing at runtime.
112+
113+
114+
C libraries
115+
-----------
116+
117+
A handful of useful C libraries are provided by C.scala. Currently functions in
118+
the following libraries are provided:
119+
120+
* `stdlib.h` via the `cscala.CStdLib` package (only `free` and `malloc`).
121+
* `stdio.h` via the `cscala.CStdIO` package.
122+
* `sys/time.h` via the `cscala.CSysTime` package (only `gettimeofday`,
123+
`timeval_subtract` and the `timeval` struct
124+
* `string.h` via the `CString` pacakge.
125+
126+
Some collections from GLib are also provided:
127+
128+
* [Doubly-linked lists](https://developer.gnome.org/glib/stable/glib-Doubly-Linked-Lists.html)
129+
via the `cscala.GListHeader` package.
130+
* [Hash tables](https://developer.gnome.org/glib/stable/glib-Hash-Tables.html)
131+
via the `cscala.GHashTableHeader` package.
132+
* [Arrays](https://developer.gnome.org/glib/stable/glib-Arrays.html) via the
133+
* `cscala.GArrayHeader` package.
134+
* [Balanced binary
135+
* trees](https://developer.gnome.org/glib/stable/glib-Balanced-Binary-Trees.html)
136+
* via the `cscala.GTreeHeader` package.
137+
138+
To use the GLib libraries, the following import is needed:
139+
140+
```scala
141+
import cscala.GLibTypes._
142+
```
143+
144+
145+
Scala collections
146+
-----------------
147+
148+
The libraries presented above can be used to prototype C implementations of
149+
Scala collections. This has already been done for a few collections:
150+
151+
* HashMaps in `cscala.collections.CHashMap`.
152+
* ArrayBuffers in `cscala.collections.CArrayBuffer`.
153+
* Lists in `cscala.collections.CList`.
154+
* Sets in `cscala.collections.CSet` (partially).
155+
* TreeSets in `cscala.collections.CTreeSet` (partially).
156+
157+
To use these collections, the following import is needed:
158+
159+
```scala
160+
import cscala.collections.CCollectionsTypes._
161+
```
162+
163+
164+
Issues
165+
======
166+
167+
* Struct declaration and selection should be cleaned up so that `->` no longer
168+
needs type parameters all the time, and declaration can be done more easily
169+
(e.g. just a case class).
170+
171+
* The `pointer_add` and `pointer_sub` methods, as well as the `->` method
172+
should be methods on `Pointer[T]`, perhaps via an implicit class.
173+
174+
* Casting is only partly implemented.
175+
176+
* Varargs functions such as printf aren't implemented.
177+

0 commit comments

Comments
 (0)