Skip to content

Commit b9562be

Browse files
committed
Make app a bit more interesting
1 parent 8a2dccd commit b9562be

File tree

10 files changed

+165
-149
lines changed

10 files changed

+165
-149
lines changed

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
SHARED_EXT := $(shell [ "$$(uname)" = "Darwin" ] && echo "dylib" || echo "so")
2+
jextract_path := $(or $(JEXTRACT_PATH), ~/Downloads/jextract-22/bin/jextract)
23

34
jextract:
4-
jextract --output java-side/ --target-package myscalalib_bindings interface.h
5+
$(jextract_path) --output java-side/ --target-package myscalalib_bindings interface.h
56

67
bindgen:
78
sn-bindgen --header interface.h --package myscalalib --export --flavour scala-native05 --scala --out scala-native-side/interface.scala

interface.h

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
extern int myscalalib_exports(int i, int r);
1+
2+
typedef enum {
3+
MULTIPLY = 1,
4+
ADD = 2
5+
} myscalalib_operation;
26

37
typedef struct {
4-
char a;
5-
char b;
6-
} myscalalib_struct;
8+
myscalalib_operation op;
9+
char* label;
10+
} myscalalib_config;
11+
712

8-
extern void myscalalib_complex(int times, myscalalib_struct* clamp, char* result);
13+
extern float myscalalib_run(myscalalib_config* config, float left, float right);
914

1015
extern int ScalaNativeInit(void);

java-side/Main.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
import myscalalib_bindings.*;
55
import java.nio.file.Paths;
6+
import java.lang.foreign.*;
67

78
public class Main {
89
public static void main(String[] args) {
10+
// Load the dynamic library
911
String dylibPath = null;
1012
if (args.length != 1) {
1113
System.err.println("First argument has to be path to dynamic library");
@@ -17,8 +19,22 @@ public static void main(String[] args) {
1719

1820
System.load(p);
1921

22+
// Make sure Scala Native GC is initialised correctly!
2023
assert (interface_h.ScalaNativeInit() == 0);
2124

22-
System.out.println(interface_h.myscalalib_exports(25, 50));
25+
// Run exported functions
26+
try (Arena arena = Arena.ofConfined()) {
27+
var config = myscalalib_config.allocate(arena);
28+
29+
myscalalib_config.label(config, arena.allocateFrom("First test"));
30+
myscalalib_config.op(config, interface_h.ADD());
31+
interface_h.myscalalib_run(config, 25.0f, 150.0f);
32+
33+
myscalalib_config.label(config, arena.allocateFrom("Second"));
34+
myscalalib_config.op(config, interface_h.MULTIPLY());
35+
interface_h.myscalalib_run(config, 50.0f, 10.0f);
36+
37+
}
38+
2339
}
2440
}

java-side/myscalalib_bindings/interface_h.java

+28-68
Original file line numberDiff line numberDiff line change
@@ -68,120 +68,80 @@ static MemoryLayout align(MemoryLayout layout, long align) {
6868
public static final AddressLayout C_POINTER = ValueLayout.ADDRESS
6969
.withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, JAVA_BYTE));
7070
public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG;
71-
72-
private static class myscalalib_exports {
73-
public static final FunctionDescriptor DESC = FunctionDescriptor.of(
74-
interface_h.C_INT,
75-
interface_h.C_INT,
76-
interface_h.C_INT
77-
);
78-
79-
public static final MemorySegment ADDR = interface_h.findOrThrow("myscalalib_exports");
80-
81-
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
82-
}
83-
71+
private static final int MULTIPLY = (int)1L;
8472
/**
85-
* Function descriptor for:
8673
* {@snippet lang=c :
87-
* extern int myscalalib_exports(int i, int r)
74+
* enum <anonymous>.MULTIPLY = 1
8875
* }
8976
*/
90-
public static FunctionDescriptor myscalalib_exports$descriptor() {
91-
return myscalalib_exports.DESC;
77+
public static int MULTIPLY() {
78+
return MULTIPLY;
9279
}
93-
80+
private static final int ADD = (int)2L;
9481
/**
95-
* Downcall method handle for:
9682
* {@snippet lang=c :
97-
* extern int myscalalib_exports(int i, int r)
83+
* enum <anonymous>.ADD = 2
9884
* }
9985
*/
100-
public static MethodHandle myscalalib_exports$handle() {
101-
return myscalalib_exports.HANDLE;
86+
public static int ADD() {
87+
return ADD;
10288
}
10389

104-
/**
105-
* Address for:
106-
* {@snippet lang=c :
107-
* extern int myscalalib_exports(int i, int r)
108-
* }
109-
*/
110-
public static MemorySegment myscalalib_exports$address() {
111-
return myscalalib_exports.ADDR;
112-
}
113-
114-
/**
115-
* {@snippet lang=c :
116-
* extern int myscalalib_exports(int i, int r)
117-
* }
118-
*/
119-
public static int myscalalib_exports(int i, int r) {
120-
var mh$ = myscalalib_exports.HANDLE;
121-
try {
122-
if (TRACE_DOWNCALLS) {
123-
traceDowncall("myscalalib_exports", i, r);
124-
}
125-
return (int)mh$.invokeExact(i, r);
126-
} catch (Throwable ex$) {
127-
throw new AssertionError("should not reach here", ex$);
128-
}
129-
}
130-
131-
private static class myscalalib_complex {
132-
public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
133-
interface_h.C_INT,
90+
private static class myscalalib_run {
91+
public static final FunctionDescriptor DESC = FunctionDescriptor.of(
92+
interface_h.C_FLOAT,
13493
interface_h.C_POINTER,
135-
interface_h.C_POINTER
94+
interface_h.C_FLOAT,
95+
interface_h.C_FLOAT
13696
);
13797

138-
public static final MemorySegment ADDR = interface_h.findOrThrow("myscalalib_complex");
98+
public static final MemorySegment ADDR = interface_h.findOrThrow("myscalalib_run");
13999

140100
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
141101
}
142102

143103
/**
144104
* Function descriptor for:
145105
* {@snippet lang=c :
146-
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
106+
* extern float myscalalib_run(myscalalib_config *config, float left, float right)
147107
* }
148108
*/
149-
public static FunctionDescriptor myscalalib_complex$descriptor() {
150-
return myscalalib_complex.DESC;
109+
public static FunctionDescriptor myscalalib_run$descriptor() {
110+
return myscalalib_run.DESC;
151111
}
152112

153113
/**
154114
* Downcall method handle for:
155115
* {@snippet lang=c :
156-
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
116+
* extern float myscalalib_run(myscalalib_config *config, float left, float right)
157117
* }
158118
*/
159-
public static MethodHandle myscalalib_complex$handle() {
160-
return myscalalib_complex.HANDLE;
119+
public static MethodHandle myscalalib_run$handle() {
120+
return myscalalib_run.HANDLE;
161121
}
162122

163123
/**
164124
* Address for:
165125
* {@snippet lang=c :
166-
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
126+
* extern float myscalalib_run(myscalalib_config *config, float left, float right)
167127
* }
168128
*/
169-
public static MemorySegment myscalalib_complex$address() {
170-
return myscalalib_complex.ADDR;
129+
public static MemorySegment myscalalib_run$address() {
130+
return myscalalib_run.ADDR;
171131
}
172132

173133
/**
174134
* {@snippet lang=c :
175-
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
135+
* extern float myscalalib_run(myscalalib_config *config, float left, float right)
176136
* }
177137
*/
178-
public static void myscalalib_complex(int times, MemorySegment clamp, MemorySegment result) {
179-
var mh$ = myscalalib_complex.HANDLE;
138+
public static float myscalalib_run(MemorySegment config, float left, float right) {
139+
var mh$ = myscalalib_run.HANDLE;
180140
try {
181141
if (TRACE_DOWNCALLS) {
182-
traceDowncall("myscalalib_complex", times, clamp, result);
142+
traceDowncall("myscalalib_run", config, left, right);
183143
}
184-
mh$.invokeExact(times, clamp, result);
144+
return (float)mh$.invokeExact(config, left, right);
185145
} catch (Throwable ex$) {
186146
throw new AssertionError("should not reach here", ex$);
187147
}

java-side/myscalalib_bindings/myscalalib_struct.java renamed to java-side/myscalalib_bindings/myscalalib_config.java

+36-35
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,22 @@
1515
/**
1616
* {@snippet lang=c :
1717
* struct {
18-
* char a;
19-
* char b;
18+
* myscalalib_operation op;
19+
* char *label;
2020
* }
2121
* }
2222
*/
23-
public class myscalalib_struct {
23+
public class myscalalib_config {
2424

25-
myscalalib_struct() {
25+
myscalalib_config() {
2626
// Should not be called directly
2727
}
2828

2929
private static final GroupLayout $LAYOUT = MemoryLayout.structLayout(
30-
interface_h.C_CHAR.withName("a"),
31-
interface_h.C_CHAR.withName("b")
32-
).withName("$anon$3:9");
30+
interface_h.C_INT.withName("op"),
31+
MemoryLayout.paddingLayout(4),
32+
interface_h.C_POINTER.withName("label")
33+
).withName("$anon$7:9");
3334

3435
/**
3536
* The layout of this struct
@@ -38,92 +39,92 @@ public static final GroupLayout layout() {
3839
return $LAYOUT;
3940
}
4041

41-
private static final OfByte a$LAYOUT = (OfByte)$LAYOUT.select(groupElement("a"));
42+
private static final OfInt op$LAYOUT = (OfInt)$LAYOUT.select(groupElement("op"));
4243

4344
/**
4445
* Layout for field:
4546
* {@snippet lang=c :
46-
* char a
47+
* myscalalib_operation op
4748
* }
4849
*/
49-
public static final OfByte a$layout() {
50-
return a$LAYOUT;
50+
public static final OfInt op$layout() {
51+
return op$LAYOUT;
5152
}
5253

53-
private static final long a$OFFSET = 0;
54+
private static final long op$OFFSET = 0;
5455

5556
/**
5657
* Offset for field:
5758
* {@snippet lang=c :
58-
* char a
59+
* myscalalib_operation op
5960
* }
6061
*/
61-
public static final long a$offset() {
62-
return a$OFFSET;
62+
public static final long op$offset() {
63+
return op$OFFSET;
6364
}
6465

6566
/**
6667
* Getter for field:
6768
* {@snippet lang=c :
68-
* char a
69+
* myscalalib_operation op
6970
* }
7071
*/
71-
public static byte a(MemorySegment struct) {
72-
return struct.get(a$LAYOUT, a$OFFSET);
72+
public static int op(MemorySegment struct) {
73+
return struct.get(op$LAYOUT, op$OFFSET);
7374
}
7475

7576
/**
7677
* Setter for field:
7778
* {@snippet lang=c :
78-
* char a
79+
* myscalalib_operation op
7980
* }
8081
*/
81-
public static void a(MemorySegment struct, byte fieldValue) {
82-
struct.set(a$LAYOUT, a$OFFSET, fieldValue);
82+
public static void op(MemorySegment struct, int fieldValue) {
83+
struct.set(op$LAYOUT, op$OFFSET, fieldValue);
8384
}
8485

85-
private static final OfByte b$LAYOUT = (OfByte)$LAYOUT.select(groupElement("b"));
86+
private static final AddressLayout label$LAYOUT = (AddressLayout)$LAYOUT.select(groupElement("label"));
8687

8788
/**
8889
* Layout for field:
8990
* {@snippet lang=c :
90-
* char b
91+
* char *label
9192
* }
9293
*/
93-
public static final OfByte b$layout() {
94-
return b$LAYOUT;
94+
public static final AddressLayout label$layout() {
95+
return label$LAYOUT;
9596
}
9697

97-
private static final long b$OFFSET = 1;
98+
private static final long label$OFFSET = 8;
9899

99100
/**
100101
* Offset for field:
101102
* {@snippet lang=c :
102-
* char b
103+
* char *label
103104
* }
104105
*/
105-
public static final long b$offset() {
106-
return b$OFFSET;
106+
public static final long label$offset() {
107+
return label$OFFSET;
107108
}
108109

109110
/**
110111
* Getter for field:
111112
* {@snippet lang=c :
112-
* char b
113+
* char *label
113114
* }
114115
*/
115-
public static byte b(MemorySegment struct) {
116-
return struct.get(b$LAYOUT, b$OFFSET);
116+
public static MemorySegment label(MemorySegment struct) {
117+
return struct.get(label$LAYOUT, label$OFFSET);
117118
}
118119

119120
/**
120121
* Setter for field:
121122
* {@snippet lang=c :
122-
* char b
123+
* char *label
123124
* }
124125
*/
125-
public static void b(MemorySegment struct, byte fieldValue) {
126-
struct.set(b$LAYOUT, b$OFFSET, fieldValue);
126+
public static void label(MemorySegment struct, MemorySegment fieldValue) {
127+
struct.set(label$LAYOUT, label$OFFSET, fieldValue);
127128
}
128129

129130
/**

scala-native-side/.scalafmt.conf

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
version = "3.7.15"
2+
runner.dialect = scala3

scala-native-side/interface.dylib

-2.02 MB
Binary file not shown.

0 commit comments

Comments
 (0)