Skip to content

Commit 2a23a38

Browse files
authored
Merge pull request #6 from desttinghim/main
Add class2zig tool
2 parents 30070dd + 6e648a6 commit 2a23a38

File tree

13 files changed

+2921
-15
lines changed

13 files changed

+2921
-15
lines changed

build.zig

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,63 @@ pub fn build(b: *std.build.Builder) void {
2626
lib.install();
2727
}
2828

29+
const java_home = b.env_map.get("JAVA_HOME") orelse @panic("JAVA_HOME not defined.");
30+
const libjvm_path = if (builtin.os.tag == .windows) "/lib" else "/lib/server";
31+
32+
{
33+
const exe = b.addExecutable("class2zig", "tools/class2zig.zig");
34+
35+
if (@hasField(std.build.LibExeObjStep, "use_stage1"))
36+
exe.use_stage1 = true;
37+
38+
exe.addPackagePath("jui", "src/jui.zig");
39+
exe.addPackagePath("cf", "dep/cf/cf.zig");
40+
41+
exe.setTarget(target);
42+
exe.setBuildMode(mode);
43+
exe.install();
44+
45+
const run_cmd = exe.run();
46+
run_cmd.step.dependOn(b.getInstallStep());
47+
if (b.args) |args| {
48+
run_cmd.addArgs(args);
49+
}
50+
51+
const run_step = b.step("class2zig", "Run class2zig tool");
52+
run_step.dependOn(&run_cmd.step);
53+
}
54+
55+
//Example
56+
{
57+
const exe = b.addExecutable("guessing_game", "examples/guessing-game/main.zig");
58+
59+
if (@hasField(std.build.LibExeObjStep, "use_stage1"))
60+
exe.use_stage1 = true;
61+
62+
exe.addPackagePath("jui", "src/jui.zig");
63+
64+
exe.addLibraryPath(b.pathJoin(&.{ java_home, libjvm_path }));
65+
exe.linkSystemLibrary("jvm");
66+
exe.linkLibC();
67+
68+
exe.setTarget(target);
69+
exe.setBuildMode(mode);
70+
exe.install();
71+
72+
const run_cmd = exe.run();
73+
run_cmd.step.dependOn(b.getInstallStep());
74+
if (b.args) |args| {
75+
run_cmd.addArgs(args);
76+
}
77+
78+
const run_step = b.step("guessing_game", "Run guessing game example");
79+
run_step.dependOn(&run_cmd.step);
80+
}
81+
2982
// Tests (it requires a JDK installed)
3083
{
31-
const java_home = b.env_map.get("JAVA_HOME") orelse @panic("JAVA_HOME not defined.");
3284
const main_tests = b.addTest("src/jui.zig");
3385

34-
const libjvm_path = if (builtin.os.tag == .windows) "/lib" else "/lib/server";
3586
if (@hasDecl(@TypeOf(main_tests.*), "addLibraryPath")) {
3687
main_tests.addLibraryPath(b.pathJoin(&.{ java_home, libjvm_path }));
3788
} else {

dep/cf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 4c65b3a58913ec16c49b4e97b2814eca94d3c06d
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
const std = @import("std");
2+
const jui = @import("jui");
3+
/// Opaque type corresponding to java/io/InputStream
4+
pub const InputStream = opaque {
5+
const classpath = "java/io/InputStream";
6+
var class_global: jui.jclass = null;
7+
var fields: struct {
8+
@"MAX_SKIP_BUFFER_SIZE_I": jui.jfieldID,
9+
@"DEFAULT_BUFFER_SIZE_I": jui.jfieldID,
10+
@"MAX_BUFFER_SIZE_I": jui.jfieldID,
11+
} = undefined;
12+
var methods: struct {
13+
@"<init>()V": jui.jmethodID,
14+
@"nullInputStream()Ljava/io/InputStream;": jui.jmethodID,
15+
@"read()I": jui.jmethodID,
16+
@"read([B)I": jui.jmethodID,
17+
@"read([BII)I": jui.jmethodID,
18+
@"readAllBytes()[B": jui.jmethodID,
19+
@"readNBytes(I)[B": jui.jmethodID,
20+
@"readNBytes([BII)I": jui.jmethodID,
21+
@"skip(J)J": jui.jmethodID,
22+
@"skipNBytes(J)V": jui.jmethodID,
23+
@"available()I": jui.jmethodID,
24+
@"close()V": jui.jmethodID,
25+
@"mark(I)V": jui.jmethodID,
26+
@"reset()V": jui.jmethodID,
27+
@"markSupported()Z": jui.jmethodID,
28+
@"transferTo(Ljava/io/OutputStream;)J": jui.jmethodID,
29+
} = undefined;
30+
pub fn load(env: *jui.JNIEnv) !void {
31+
struct {
32+
var runner = std.once(_runner);
33+
var _env: *jui.JNIEnv = undefined;
34+
var _err: ?Error = null;
35+
36+
const Error =
37+
jui.JNIEnv.FindClassError ||
38+
jui.JNIEnv.NewReferenceError ||
39+
jui.JNIEnv.GetFieldIdError ||
40+
jui.JNIEnv.GetMethodIdError ||
41+
jui.JNIEnv.GetStaticFieldIdError ||
42+
jui.JNIEnv.GetStaticMethodIdError;
43+
44+
fn _load(arg: *jui.JNIEnv) !void {
45+
_env = arg;
46+
runner.call();
47+
if (_err) |e| return e;
48+
}
49+
50+
fn _runner() void {
51+
_run(_env) catch |e| { _err = e; };
52+
}
53+
54+
fn _run(inner_env: *jui.JNIEnv) !void {
55+
const class_local = try inner_env.findClass(classpath);
56+
class_global = try inner_env.newReference(.global, class_local);
57+
const class = class_global orelse return error.NoClassDefFoundError;
58+
//
59+
fields = .{
60+
.@"MAX_SKIP_BUFFER_SIZE_I" = try inner_env.getStaticFieldId(class, "MAX_SKIP_BUFFER_SIZE", "I"),
61+
.@"DEFAULT_BUFFER_SIZE_I" = try inner_env.getStaticFieldId(class, "DEFAULT_BUFFER_SIZE", "I"),
62+
.@"MAX_BUFFER_SIZE_I" = try inner_env.getStaticFieldId(class, "MAX_BUFFER_SIZE", "I"),
63+
};
64+
methods = .{
65+
.@"<init>()V" = try inner_env.getMethodId(class, "<init>", "()V"),
66+
.@"nullInputStream()Ljava/io/InputStream;" = try inner_env.getStaticMethodId(class, "nullInputStream", "()Ljava/io/InputStream;"),
67+
.@"read()I" = try inner_env.getMethodId(class, "read", "()I"),
68+
.@"read([B)I" = try inner_env.getMethodId(class, "read", "([B)I"),
69+
.@"read([BII)I" = try inner_env.getMethodId(class, "read", "([BII)I"),
70+
.@"readAllBytes()[B" = try inner_env.getMethodId(class, "readAllBytes", "()[B"),
71+
.@"readNBytes(I)[B" = try inner_env.getMethodId(class, "readNBytes", "(I)[B"),
72+
.@"readNBytes([BII)I" = try inner_env.getMethodId(class, "readNBytes", "([BII)I"),
73+
.@"skip(J)J" = try inner_env.getMethodId(class, "skip", "(J)J"),
74+
.@"skipNBytes(J)V" = try inner_env.getMethodId(class, "skipNBytes", "(J)V"),
75+
.@"available()I" = try inner_env.getMethodId(class, "available", "()I"),
76+
.@"close()V" = try inner_env.getMethodId(class, "close", "()V"),
77+
.@"mark(I)V" = try inner_env.getMethodId(class, "mark", "(I)V"),
78+
.@"reset()V" = try inner_env.getMethodId(class, "reset", "()V"),
79+
.@"markSupported()Z" = try inner_env.getMethodId(class, "markSupported", "()Z"),
80+
.@"transferTo(Ljava/io/OutputStream;)J" = try inner_env.getMethodId(class, "transferTo", "(Ljava/io/OutputStream;)J"),
81+
};
82+
83+
}
84+
}._load(env) catch |e| return e;
85+
}
86+
pub fn @"get_MAX_SKIP_BUFFER_SIZE_I"(env: *jui.JNIEnv) !jui.jint {
87+
try load(env);
88+
const class = class_global orelse return error.ClassNotFound;
89+
return env.getStaticField(.int, class, fields.@"MAX_SKIP_BUFFER_SIZE_I");
90+
}
91+
pub fn @"get_DEFAULT_BUFFER_SIZE_I"(env: *jui.JNIEnv) !jui.jint {
92+
try load(env);
93+
const class = class_global orelse return error.ClassNotFound;
94+
return env.getStaticField(.int, class, fields.@"DEFAULT_BUFFER_SIZE_I");
95+
}
96+
pub fn @"get_MAX_BUFFER_SIZE_I"(env: *jui.JNIEnv) !jui.jint {
97+
try load(env);
98+
const class = class_global orelse return error.ClassNotFound;
99+
return env.getStaticField(.int, class, fields.@"MAX_BUFFER_SIZE_I");
100+
}
101+
pub fn @"<init>()V"(env: *jui.JNIEnv) !*@This() {
102+
try load(env);
103+
const class = class_global orelse return error.ClassNotLoaded;
104+
return @ptrCast(*@This(), try env.newObject(class, methods.@"<init>()V", null));
105+
}
106+
pub fn @"nullInputStream()Ljava/io/InputStream;"(env: *jui.JNIEnv) !jui.jobject {
107+
try load(env);
108+
const class = class_global orelse return error.ClassNotFound;
109+
return env.callStaticMethod(.object, class, methods.@"nullInputStream()Ljava/io/InputStream;", null);
110+
}
111+
pub fn @"read()I"(self: *@This(), env: *jui.JNIEnv) !jui.jint {
112+
try load(env);
113+
_ = class_global orelse return error.ClassNotFound;
114+
return env.callMethod(.int, self, methods.@"read()I", null);
115+
}
116+
pub fn @"read([B)I"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jarray) !jui.jint {
117+
try load(env);
118+
_ = class_global orelse return error.ClassNotFound;
119+
return env.callMethod(.int, self, methods.@"read([B)I", &[_]jui.jvalue{jui.jvalue.toJValue(arg0)});
120+
}
121+
pub fn @"read([BII)I"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jarray, arg1: jui.jint, arg2: jui.jint) !jui.jint {
122+
try load(env);
123+
_ = class_global orelse return error.ClassNotFound;
124+
return env.callMethod(.int, self, methods.@"read([BII)I", &[_]jui.jvalue{jui.jvalue.toJValue(arg0), jui.jvalue.toJValue(arg1), jui.jvalue.toJValue(arg2)});
125+
}
126+
pub fn @"readAllBytes()[B"(self: *@This(), env: *jui.JNIEnv) !jui.jarray {
127+
try load(env);
128+
_ = class_global orelse return error.ClassNotFound;
129+
return env.callMethod(.array, self, methods.@"readAllBytes()[B", null);
130+
}
131+
pub fn @"readNBytes(I)[B"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jint) !jui.jarray {
132+
try load(env);
133+
_ = class_global orelse return error.ClassNotFound;
134+
return env.callMethod(.array, self, methods.@"readNBytes(I)[B", &[_]jui.jvalue{jui.jvalue.toJValue(arg0)});
135+
}
136+
pub fn @"readNBytes([BII)I"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jarray, arg1: jui.jint, arg2: jui.jint) !jui.jint {
137+
try load(env);
138+
_ = class_global orelse return error.ClassNotFound;
139+
return env.callMethod(.int, self, methods.@"readNBytes([BII)I", &[_]jui.jvalue{jui.jvalue.toJValue(arg0), jui.jvalue.toJValue(arg1), jui.jvalue.toJValue(arg2)});
140+
}
141+
pub fn @"skip(J)J"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jlong) !jui.jlong {
142+
try load(env);
143+
_ = class_global orelse return error.ClassNotFound;
144+
return env.callMethod(.long, self, methods.@"skip(J)J", &[_]jui.jvalue{jui.jvalue.toJValue(arg0)});
145+
}
146+
pub fn @"skipNBytes(J)V"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jlong) !void {
147+
try load(env);
148+
_ = class_global orelse return error.ClassNotFound;
149+
return env.callMethod(.void, self, methods.@"skipNBytes(J)V", &[_]jui.jvalue{jui.jvalue.toJValue(arg0)});
150+
}
151+
pub fn @"available()I"(self: *@This(), env: *jui.JNIEnv) !jui.jint {
152+
try load(env);
153+
_ = class_global orelse return error.ClassNotFound;
154+
return env.callMethod(.int, self, methods.@"available()I", null);
155+
}
156+
pub fn @"close()V"(self: *@This(), env: *jui.JNIEnv) !void {
157+
try load(env);
158+
_ = class_global orelse return error.ClassNotFound;
159+
return env.callMethod(.void, self, methods.@"close()V", null);
160+
}
161+
pub fn @"mark(I)V"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jint) !void {
162+
try load(env);
163+
_ = class_global orelse return error.ClassNotFound;
164+
return env.callMethod(.void, self, methods.@"mark(I)V", &[_]jui.jvalue{jui.jvalue.toJValue(arg0)});
165+
}
166+
pub fn @"reset()V"(self: *@This(), env: *jui.JNIEnv) !void {
167+
try load(env);
168+
_ = class_global orelse return error.ClassNotFound;
169+
return env.callMethod(.void, self, methods.@"reset()V", null);
170+
}
171+
pub fn @"markSupported()Z"(self: *@This(), env: *jui.JNIEnv) !jui.jboolean {
172+
try load(env);
173+
_ = class_global orelse return error.ClassNotFound;
174+
return env.callMethod(.boolean, self, methods.@"markSupported()Z", null);
175+
}
176+
pub fn @"transferTo(Ljava/io/OutputStream;)J"(self: *@This(), env: *jui.JNIEnv, arg0: jui.jobject) !jui.jlong {
177+
try load(env);
178+
_ = class_global orelse return error.ClassNotFound;
179+
return env.callMethod(.long, self, methods.@"transferTo(Ljava/io/OutputStream;)J", &[_]jui.jvalue{jui.jvalue.toJValue(arg0)});
180+
}
181+
182+
};

0 commit comments

Comments
 (0)