Skip to content

Commit 8a2dccd

Browse files
committed
Makefile and make it pure Java
0 parents  commit 8a2dccd

File tree

11 files changed

+598
-0
lines changed

11 files changed

+598
-0
lines changed

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
project/target
2+
project/project
3+
.metals
4+
.bloop
5+
.vscode
6+
*.class
7+
*.sjsr
8+
9+
project/.bloop
10+
11+
.sbt
12+
13+
modules/core/target
14+
15+
root/target
16+
target
17+
18+
.bsp
19+
20+
*.log
21+
22+
project/metals.sbt
23+
.scala-build

.scalafmt.conf

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version = "3.8.6"
2+
3+
runner.dialect = scala3
4+
rewrite.scala3.insertEndMarkerMinLines = 10
5+
rewrite.scala3.removeOptionalBraces = true
6+
rewrite.scala3.convertToNewSyntax = true
7+
align.preset = more
8+
9+
fileOverride {
10+
"glob:**.sbt" {
11+
runner.dialect = scala212source3
12+
}
13+
14+
"glob:**/project/plugins.sbt" {
15+
runner.dialect = scala212source3
16+
newlines.topLevelStatementBlankLines = [
17+
{
18+
blanks = 1,
19+
minBreaks = 0
20+
}
21+
]
22+
}
23+
}
24+
25+
rewrite {
26+
trailingCommas.style = "always"
27+
}

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
SHARED_EXT := $(shell [ "$$(uname)" = "Darwin" ] && echo "dylib" || echo "so")
2+
3+
jextract:
4+
jextract --output java-side/ --target-package myscalalib_bindings interface.h
5+
6+
bindgen:
7+
sn-bindgen --header interface.h --package myscalalib --export --flavour scala-native05 --scala --out scala-native-side/interface.scala
8+
9+
scala-lib:
10+
cd scala-native-side && scala-cli package . -f -o ../scala-lib.$(SHARED_EXT)
11+
12+
run: scala-lib
13+
cd java-side && scala-cli run . -- ../scala-lib.$(SHARED_EXT)
14+

interface.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
extern int myscalalib_exports(int i, int r);
2+
3+
typedef struct {
4+
char a;
5+
char b;
6+
} myscalalib_struct;
7+
8+
extern void myscalalib_complex(int times, myscalalib_struct* clamp, char* result);
9+
10+
extern int ScalaNativeInit(void);

java-side/Main.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//> using jvm 23
2+
//> using javaOpt --enable-native-access=ALL-UNNAMED
3+
4+
import myscalalib_bindings.*;
5+
import java.nio.file.Paths;
6+
7+
public class Main {
8+
public static void main(String[] args) {
9+
String dylibPath = null;
10+
if (args.length != 1) {
11+
System.err.println("First argument has to be path to dynamic library");
12+
System.exit(1);
13+
} else {
14+
dylibPath = args[0];
15+
}
16+
var p = Paths.get(dylibPath).toAbsolutePath().toString();
17+
18+
System.load(p);
19+
20+
assert (interface_h.ScalaNativeInit() == 0);
21+
22+
System.out.println(interface_h.myscalalib_exports(25, 50));
23+
}
24+
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// Generated by jextract
2+
3+
package myscalalib_bindings;
4+
5+
import java.lang.invoke.*;
6+
import java.lang.foreign.*;
7+
import java.nio.ByteOrder;
8+
import java.util.*;
9+
import java.util.function.*;
10+
import java.util.stream.*;
11+
12+
import static java.lang.foreign.ValueLayout.*;
13+
import static java.lang.foreign.MemoryLayout.PathElement.*;
14+
15+
public class interface_h {
16+
17+
interface_h() {
18+
// Should not be called directly
19+
}
20+
21+
static final Arena LIBRARY_ARENA = Arena.ofAuto();
22+
static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls");
23+
24+
static void traceDowncall(String name, Object... args) {
25+
String traceArgs = Arrays.stream(args)
26+
.map(Object::toString)
27+
.collect(Collectors.joining(", "));
28+
System.out.printf("%s(%s)\n", name, traceArgs);
29+
}
30+
31+
static MemorySegment findOrThrow(String symbol) {
32+
return SYMBOL_LOOKUP.find(symbol)
33+
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol));
34+
}
35+
36+
static MethodHandle upcallHandle(Class<?> fi, String name, FunctionDescriptor fdesc) {
37+
try {
38+
return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType());
39+
} catch (ReflectiveOperationException ex) {
40+
throw new AssertionError(ex);
41+
}
42+
}
43+
44+
static MemoryLayout align(MemoryLayout layout, long align) {
45+
return switch (layout) {
46+
case PaddingLayout p -> p;
47+
case ValueLayout v -> v.withByteAlignment(align);
48+
case GroupLayout g -> {
49+
MemoryLayout[] alignedMembers = g.memberLayouts().stream()
50+
.map(m -> align(m, align)).toArray(MemoryLayout[]::new);
51+
yield g instanceof StructLayout ?
52+
MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers);
53+
}
54+
case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align));
55+
};
56+
}
57+
58+
static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup()
59+
.or(Linker.nativeLinker().defaultLookup());
60+
61+
public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN;
62+
public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE;
63+
public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT;
64+
public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT;
65+
public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG;
66+
public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT;
67+
public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE;
68+
public static final AddressLayout C_POINTER = ValueLayout.ADDRESS
69+
.withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, JAVA_BYTE));
70+
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+
84+
/**
85+
* Function descriptor for:
86+
* {@snippet lang=c :
87+
* extern int myscalalib_exports(int i, int r)
88+
* }
89+
*/
90+
public static FunctionDescriptor myscalalib_exports$descriptor() {
91+
return myscalalib_exports.DESC;
92+
}
93+
94+
/**
95+
* Downcall method handle for:
96+
* {@snippet lang=c :
97+
* extern int myscalalib_exports(int i, int r)
98+
* }
99+
*/
100+
public static MethodHandle myscalalib_exports$handle() {
101+
return myscalalib_exports.HANDLE;
102+
}
103+
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,
134+
interface_h.C_POINTER,
135+
interface_h.C_POINTER
136+
);
137+
138+
public static final MemorySegment ADDR = interface_h.findOrThrow("myscalalib_complex");
139+
140+
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
141+
}
142+
143+
/**
144+
* Function descriptor for:
145+
* {@snippet lang=c :
146+
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
147+
* }
148+
*/
149+
public static FunctionDescriptor myscalalib_complex$descriptor() {
150+
return myscalalib_complex.DESC;
151+
}
152+
153+
/**
154+
* Downcall method handle for:
155+
* {@snippet lang=c :
156+
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
157+
* }
158+
*/
159+
public static MethodHandle myscalalib_complex$handle() {
160+
return myscalalib_complex.HANDLE;
161+
}
162+
163+
/**
164+
* Address for:
165+
* {@snippet lang=c :
166+
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
167+
* }
168+
*/
169+
public static MemorySegment myscalalib_complex$address() {
170+
return myscalalib_complex.ADDR;
171+
}
172+
173+
/**
174+
* {@snippet lang=c :
175+
* extern void myscalalib_complex(int times, myscalalib_struct *clamp, char *result)
176+
* }
177+
*/
178+
public static void myscalalib_complex(int times, MemorySegment clamp, MemorySegment result) {
179+
var mh$ = myscalalib_complex.HANDLE;
180+
try {
181+
if (TRACE_DOWNCALLS) {
182+
traceDowncall("myscalalib_complex", times, clamp, result);
183+
}
184+
mh$.invokeExact(times, clamp, result);
185+
} catch (Throwable ex$) {
186+
throw new AssertionError("should not reach here", ex$);
187+
}
188+
}
189+
190+
private static class ScalaNativeInit {
191+
public static final FunctionDescriptor DESC = FunctionDescriptor.of(
192+
interface_h.C_INT );
193+
194+
public static final MemorySegment ADDR = interface_h.findOrThrow("ScalaNativeInit");
195+
196+
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
197+
}
198+
199+
/**
200+
* Function descriptor for:
201+
* {@snippet lang=c :
202+
* extern int ScalaNativeInit()
203+
* }
204+
*/
205+
public static FunctionDescriptor ScalaNativeInit$descriptor() {
206+
return ScalaNativeInit.DESC;
207+
}
208+
209+
/**
210+
* Downcall method handle for:
211+
* {@snippet lang=c :
212+
* extern int ScalaNativeInit()
213+
* }
214+
*/
215+
public static MethodHandle ScalaNativeInit$handle() {
216+
return ScalaNativeInit.HANDLE;
217+
}
218+
219+
/**
220+
* Address for:
221+
* {@snippet lang=c :
222+
* extern int ScalaNativeInit()
223+
* }
224+
*/
225+
public static MemorySegment ScalaNativeInit$address() {
226+
return ScalaNativeInit.ADDR;
227+
}
228+
229+
/**
230+
* {@snippet lang=c :
231+
* extern int ScalaNativeInit()
232+
* }
233+
*/
234+
public static int ScalaNativeInit() {
235+
var mh$ = ScalaNativeInit.HANDLE;
236+
try {
237+
if (TRACE_DOWNCALLS) {
238+
traceDowncall("ScalaNativeInit");
239+
}
240+
return (int)mh$.invokeExact();
241+
} catch (Throwable ex$) {
242+
throw new AssertionError("should not reach here", ex$);
243+
}
244+
}
245+
}
246+

0 commit comments

Comments
 (0)