Skip to content

Commit 27a5643

Browse files
committed
Update documentation and readme
1 parent 76125a8 commit 27a5643

File tree

9 files changed

+111
-64
lines changed

9 files changed

+111
-64
lines changed

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,35 @@ object vector {
5353
def y: native.CFloat = !p._2
5454
def y_=(value: native.CFloat): Unit = !p._2 = value
5555
}
56-
def struct_point()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point]
5756
5857
implicit class struct_vector_ops(val p: native.Ptr[struct_vector]) extends AnyVal {
5958
def a: native.Ptr[struct_point] = p._1
6059
def a_=(value: native.Ptr[struct_point]): Unit = !p._1 = !value
6160
def b: native.Ptr[struct_point] = p._2
6261
def b_=(value: native.Ptr[struct_point]): Unit = !p._2 = !value
6362
}
64-
def struct_vector()(implicit z: native.Zone): native.Ptr[struct_vector] = native.alloc[struct_vector]
63+
}
64+
65+
object struct_point {
66+
import implicits._
67+
def apply()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point]
68+
def apply(x: native.CFloat, y: native.CFloat)(implicit z: native.Zone): native.Ptr[struct_point] = {
69+
val ptr = native.alloc[struct_point]
70+
ptr.x = x
71+
ptr.y = y
72+
ptr
73+
}
74+
}
75+
76+
object struct_vector {
77+
import implicits._
78+
def apply()(implicit z: native.Zone): native.Ptr[struct_vector] = native.alloc[struct_vector]
79+
def apply(a: native.Ptr[struct_point], b: native.Ptr[struct_point])(implicit z: native.Zone): native.Ptr[struct_vector] = {
80+
val ptr = native.alloc[struct_vector]
81+
ptr.a = a
82+
ptr.b = b
83+
ptr
84+
}
6585
}
6686
}
6787
```

build.sbt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ lazy val docs = project("docs")
146146
.link("vector")
147147
.packageName("org.example")
148148
},
149+
nativeBindgenPath := {
150+
Some(
151+
(ThisBuild / baseDirectory).value / "bindgen/target/scala-native-bindgen")
152+
},
149153
Test / nativeBindgen / target := (Test / scalaSource).value / "org/example",
150154
nativeLinkStubs := true,
151155
compileTask("vector", Test / resourceDirectory),

docs/src/paradox/using-generated-bindings.md

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,52 @@ Consider following header file:
44

55
@@snip [vector.h] (../test/resources/vector.h)
66

7-
Bindgen will generate type aliases for the structs, binding for function `add`
8-
and helper functions that make usage of structs easier.
7+
Bindgen will output
8+
* type aliases for the structs
9+
* binding for function `cosine`
10+
* helper functions that make usage of structs easier
911

1012
@@snip [vector.h] (../test/scala/org/example/vector.scala)
1113

12-
Let's write code that creates two vectors, adds them and prints resulting
13-
vector.
14+
Let's write code that creates two line segments and prints angel between them.
1415

15-
First we need to create points for vectors. We will use `native.Zone` to
16+
First we need to create points. We will use `native.Zone` to
1617
allocate struct (more information on memory management can be found
1718
here: [Scala Native memory management]).
1819

19-
Helper object `mylibHelpers` contains function for struct allocation.
20-
To import it use `import mylibHelpers._`
20+
Generated bindings contain helper functions that make struct allocation easier.
21+
To import them use `import org.example.vector._`
2122

22-
Let's create points for first vector:
23+
Let's create two points and the first line segment:
2324

2425
@@snip [step-1] (../test/scala/org/scalanative/bindgen/docs/VectorSpec.scala) { #step-1 }
2526

26-
Now we want to set fields of created points. Scala Native provides access
27-
to fields by using `_N` methods where `N` is index of a field
28-
(see [Scala Native memory layout types]).
27+
There is no need to create points manually, just call `struct_lineSegment`
28+
constructor and set point coordinates using fields setters.
2929

30-
Bindgen generates implicit helper classes that wrap calls to `_N` in functions
31-
with meaningful names. We already imported helper class, so we can use the
32-
functions:
30+
Scala Native allows us to access a field by using `_N` method where `N` is index of a field
31+
(see [Scala Native memory layout types]) but it is not convenient because we have to
32+
match indices with fields names.
33+
34+
Bindgen provides implicit helper classes that wrap calls to `_N` in functions
35+
with meaningful names. To import these classes add `import org.example.vector.implicits._`
36+
to your code:
3337

3438
@@snip [step-2] (../test/scala/org/scalanative/bindgen/docs/VectorSpec.scala) { #step-2 }
3539

36-
Lets create first vector. Note that `struct_vector` contains
37-
fields of type `struct_point` but setters accept variables of type
38-
`native.Ptr[struct_point]`. It helps to avoid Scala Native limitation that
39-
does not allow passing structs and arrays by value
40-
(see @github[scala-native/scala-native#555](scala-native/scala-native#555)).
40+
@@@ note
41+
42+
Note that `struct_lineSegment` contains fields of value type `struct_point`
43+
but setters accept variables of type `native.Ptr[struct_point]`.
44+
It helps to avoid Scala Native limitation that does not allow passing structs
45+
and arrays by value (see @github[scala-native/scala-native#555](scala-native/scala-native#555)).
46+
47+
@@@
4148

42-
@@snip [step-3] (../test/scala/org/scalanative/bindgen/docs/VectorSpec.scala) { #step-3 }
49+
Now we can calculate angel between line segments:
4350

44-
Repeat these steps to create second vector. Once both vectors are created we can
45-
call `add` function and print the result:
51+
@@snip [step-3] (../test/scala/org/scalanative/bindgen/docs/VectorSpec.scala) { #step-2 }
4652

47-
@@snip [step-4] (../test/scala/org/scalanative/bindgen/docs/VectorSpec.scala) { #step-4 }
4853

4954
[Scala Native memory management]: http://www.scala-native.org/en/latest/user/interop.html#memory-management
5055
[Scala Native memory layout types]: http://www.scala-native.org/en/latest/user/interop.html#memory-layout-types

docs/src/test/resources/vector.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
#include "vector.h"
2+
#include <math.h>
23
#include <stdlib.h>
34

4-
struct vector *add(struct vector *v1, struct vector *v2) {
5-
struct vector *out = malloc(sizeof(struct vector));
6-
7-
if (!out)
8-
return NULL;
9-
10-
out->a.x = v1->a.x + v2->a.x;
11-
out->a.y = v1->a.y + v2->a.y;
12-
out->b.x = v1->b.x + v2->b.x;
13-
out->b.y = v1->b.y + v2->b.y;
14-
15-
return out;
16-
}
5+
float cosine(struct lineSegment *v1, struct lineSegment *v2) {
6+
float v1x = fabsf(v1->b.x - v1->a.x);
7+
float v1y = fabsf(v1->b.y - v1->a.y);
8+
float v1Length = sqrtf(v1x * v1x + v1y * v1y);
9+
float v2x = fabsf(v2->b.x - v2->a.x);
10+
float v2y = fabsf(v2->b.y - v2->a.y);
11+
float v2Length = sqrtf(v2x * v2x + v2y * v2y);
12+
return (v1x * v2x + v1y * v2y) / (v1Length * v2Length);
13+
}

docs/src/test/resources/vector.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ struct point {
33
float y;
44
};
55

6-
struct vector {
6+
struct lineSegment {
77
struct point a;
88
struct point b;
99
};
1010

11-
struct vector *add(struct vector *v1, struct vector *v2);
11+
float cosine(struct lineSegment *v1, struct lineSegment *v2);

docs/src/test/scala/org/example/vector.scala

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import scala.scalanative.native._
77
@native.extern
88
object vector {
99
type struct_point = native.CStruct2[native.CFloat, native.CFloat]
10-
type struct_vector = native.CStruct2[struct_point, struct_point]
11-
def add(v1: native.Ptr[struct_vector], v2: native.Ptr[struct_vector]): native.Ptr[struct_vector] = native.extern
10+
type struct_lineSegment = native.CStruct2[struct_point, struct_point]
11+
def cosine(v1: native.Ptr[struct_lineSegment], v2: native.Ptr[struct_lineSegment]): native.CFloat = native.extern
1212

1313
object implicits {
1414
implicit class struct_point_ops(val p: native.Ptr[struct_point]) extends AnyVal {
@@ -17,14 +17,34 @@ object vector {
1717
def y: native.CFloat = !p._2
1818
def y_=(value: native.CFloat): Unit = !p._2 = value
1919
}
20-
def struct_point()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point]
2120

22-
implicit class struct_vector_ops(val p: native.Ptr[struct_vector]) extends AnyVal {
21+
implicit class struct_lineSegment_ops(val p: native.Ptr[struct_lineSegment]) extends AnyVal {
2322
def a: native.Ptr[struct_point] = p._1
2423
def a_=(value: native.Ptr[struct_point]): Unit = !p._1 = !value
2524
def b: native.Ptr[struct_point] = p._2
2625
def b_=(value: native.Ptr[struct_point]): Unit = !p._2 = !value
2726
}
28-
def struct_vector()(implicit z: native.Zone): native.Ptr[struct_vector] = native.alloc[struct_vector]
27+
}
28+
29+
object struct_point {
30+
import implicits._
31+
def apply()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point]
32+
def apply(x: native.CFloat, y: native.CFloat)(implicit z: native.Zone): native.Ptr[struct_point] = {
33+
val ptr = native.alloc[struct_point]
34+
ptr.x = x
35+
ptr.y = y
36+
ptr
37+
}
38+
}
39+
40+
object struct_lineSegment {
41+
import implicits._
42+
def apply()(implicit z: native.Zone): native.Ptr[struct_lineSegment] = native.alloc[struct_lineSegment]
43+
def apply(a: native.Ptr[struct_point], b: native.Ptr[struct_point])(implicit z: native.Zone): native.Ptr[struct_lineSegment] = {
44+
val ptr = native.alloc[struct_lineSegment]
45+
ptr.a = a
46+
ptr.b = b
47+
ptr
48+
}
2949
}
3050
}

docs/src/test/scala/org/scalanative/bindgen/docs/VectorSpec.scala

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,32 @@ class VectorSpec extends FunSpec {
66
describe("vector") {
77
it("using generated bindings") {
88
//#step-1
9+
import org.example.vector._
910
import scala.scalanative.native.Zone
10-
import org.example.vector
11-
import org.example.vector.implicits._
1211

1312
Zone { implicit zone =>
14-
val vec1p1 = struct_point()
15-
val vec1p2 = struct_point()
13+
val p1 = struct_point(1, 1)
14+
val p2 = struct_point(7, 4)
15+
16+
val lineSegment1 = struct_lineSegment(p1, p2)
1617
//#step-1
1718
//#step-2
18-
vec1p1.x = 0
19-
vec1p1.y = 1
19+
import org.example.vector.implicits._
20+
21+
val lineSegment2 = struct_lineSegment()
2022

21-
vec1p2.x = 6
22-
vec1p2.y = 3
23+
lineSegment2.a.x = 3
24+
lineSegment2.a.y = 4
25+
lineSegment2.b = struct_point(5, 0)
2326
//#step-2
2427
//#step-3
25-
val vec1 = struct_vector()
26-
vec1.a = vec1p1
27-
vec1.b = vec1p2
28+
println(cosine(lineSegment1, lineSegment2))
2829
//#step-3
29-
val vec2 = vec1
30-
//#step-4
31-
val vec3 = vector.add(vec1, vec2)
32-
println(s"(${vec3.a.x}, ${vec3.a.y}), (${vec3.b.x}, ${vec3.b.y})")
33-
//#step-4
34-
assert(vec3.a.x == vec1.a.x + vec2.a.x)
30+
import org.scalactic.TolerantNumerics
31+
val epsilon = 1e-3f
32+
assert(
33+
(0.8.toFloat === cosine(lineSegment1, lineSegment2))(
34+
TolerantNumerics.tolerantFloatEquality(epsilon)))
3535
//#step-1
3636
}
3737
//#step-1

project/plugins.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0")
99

1010
libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value
1111

12-
val VERSION = "0.3.0-RC1"
12+
val VERSION = "0.3.0-RC2"
1313

1414
//#sbt-plugin-example
1515
addSbtPlugin("org.scala-native.bindgen" % "sbt-scala-native-bindgen" % VERSION)

tests/samples/src/test/scala/org/scalanative/bindgen/samples/StructTests.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ object StructTests extends TestSuite {
6060
!anonymousStruct._1 = 'a'
6161
!anonymousStruct._2 = 42
6262

63-
val structWithAnonymousStruct = Struct.struct_structWithAnonymousStruct()
63+
val structWithAnonymousStruct =
64+
Struct.struct_structWithAnonymousStruct()
6465
structWithAnonymousStruct.anonymousStruct = anonymousStruct
6566

6667
assert(

0 commit comments

Comments
 (0)