mirror of https://github.com/adamdruppe/arsd.git
more stuff!
This commit is contained in:
parent
eae5b84779
commit
c3a590d0fb
176
jni.d
176
jni.d
|
@ -191,35 +191,114 @@ private string getJavaName(alias a)() {
|
|||
return name;
|
||||
}
|
||||
|
||||
/+
|
||||
/+ Java class file definitions { +/
|
||||
// see: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6
|
||||
|
||||
import arsd.declarativeloader;
|
||||
|
||||
struct cp_info {
|
||||
|
||||
enum CONSTANT_Class = 7; // sizeof = 2
|
||||
struct CONSTANT_Class_info {
|
||||
@BigEndian:
|
||||
ushort name_index;
|
||||
}
|
||||
enum CONSTANT_Fieldref = 9; // sizeof = 4
|
||||
struct CONSTANT_Fieldref_info {
|
||||
@BigEndian:
|
||||
ushort class_index;
|
||||
ushort name_and_type_index;
|
||||
}
|
||||
enum CONSTANT_Methodref = 10; // sizeof = 4
|
||||
struct CONSTANT_Methodref_info {
|
||||
@BigEndian:
|
||||
ushort class_index;
|
||||
ushort name_and_type_index;
|
||||
}
|
||||
enum CONSTANT_InterfaceMethodref = 11; // sizeof = 4
|
||||
struct CONSTANT_InterfaceMethodref_info {
|
||||
@BigEndian:
|
||||
ushort class_index;
|
||||
ushort name_and_type_index;
|
||||
}
|
||||
enum CONSTANT_String = 8; // sizeof = 2
|
||||
struct CONSTANT_String_info {
|
||||
@BigEndian:
|
||||
ushort string_index;
|
||||
}
|
||||
enum CONSTANT_Integer = 3; // sizeof = 4
|
||||
struct CONSTANT_Integer_info {
|
||||
@BigEndian:
|
||||
int bytes;
|
||||
}
|
||||
enum CONSTANT_Float = 4; // sizeof = 4
|
||||
struct CONSTANT_Float_info {
|
||||
@BigEndian:
|
||||
float bytes;
|
||||
}
|
||||
enum CONSTANT_Long = 5; // sizeof = 8, but eats two slots
|
||||
struct CONSTANT_Long_info {
|
||||
@BigEndian:
|
||||
long bytes;
|
||||
}
|
||||
enum CONSTANT_Double = 6; // sizeof = 8, but eats two slots
|
||||
struct CONSTANT_Double_info {
|
||||
@BigEndian:
|
||||
double bytes;
|
||||
}
|
||||
enum CONSTANT_NameAndType = 12; // sizeof = 2
|
||||
struct CONSTANT_NameAndType_info {
|
||||
@BigEndian:
|
||||
ushort name_index;
|
||||
ushort descriptor_index;
|
||||
}
|
||||
enum CONSTANT_Utf8 = 1; // sizeof = 2 + length
|
||||
struct CONSTANT_Utf8_info {
|
||||
@BigEndian:
|
||||
ushort length;
|
||||
@NumElements!length char[] bytes; // actually modified UTF-8 but meh
|
||||
}
|
||||
enum CONSTANT_MethodHandle = 15; // sizeof = 3
|
||||
struct CONSTANT_MethodHandle_info {
|
||||
@BigEndian:
|
||||
ubyte reference_kind;
|
||||
ushort reference_index;
|
||||
}
|
||||
enum CONSTANT_MethodType = 16; // sizeof = 2; descriptor index
|
||||
struct CONSTANT_MethodType_info {
|
||||
@BigEndian:
|
||||
ushort descriptor_index;
|
||||
}
|
||||
enum CONSTANT_InvokeDynamic = 18; // sizeof = 4
|
||||
struct CONSTANT_InvokeDynamic_info {
|
||||
@BigEndian:
|
||||
ushort bootstrap_method_attr_index;
|
||||
ushort name_and_type_index;
|
||||
}
|
||||
|
||||
ubyte tag;
|
||||
union {
|
||||
|
||||
@Tagged!(tag)
|
||||
union Info {
|
||||
@Tag(CONSTANT_Class) CONSTANT_Class_info class_info;
|
||||
@Tag(CONSTANT_Fieldref) CONSTANT_Fieldref_info fieldref_info;
|
||||
@Tag(CONSTANT_Methodref) CONSTANT_Methodref_info methodref_info;
|
||||
@Tag(CONSTANT_InterfaceMethodref) CONSTANT_InterfaceMethodref_info interfaceMethodref_info;
|
||||
@Tag(CONSTANT_String) CONSTANT_String_info string_info;
|
||||
@Tag(CONSTANT_Integer) CONSTANT_Integer_info integer_info;
|
||||
@Tag(CONSTANT_Float) CONSTANT_Float_info float_info;
|
||||
@Tag(CONSTANT_Long) CONSTANT_Long_info long_info;
|
||||
@Tag(CONSTANT_Double) CONSTANT_Double_info double_info;
|
||||
@Tag(CONSTANT_NameAndType) CONSTANT_NameAndType_info nameAndType_info;
|
||||
@Tag(CONSTANT_Utf8) CONSTANT_Utf8_info utf8_info;
|
||||
@Tag(CONSTANT_MethodHandle) CONSTANT_MethodHandle_info methodHandle_info;
|
||||
@Tag(CONSTANT_MethodType) CONSTANT_MethodType_info methodType_info;
|
||||
@Tag(CONSTANT_InvokeDynamic) CONSTANT_InvokeDynamic_info invokeDynamic_info;
|
||||
}
|
||||
ubyte[] info;
|
||||
Info info;
|
||||
}
|
||||
|
||||
struct field_info {
|
||||
@BigEndian:
|
||||
|
||||
enum ACC_PUBLIC = 0x0001;
|
||||
enum ACC_PRIVATE = 0x0002;
|
||||
|
@ -235,15 +314,16 @@ struct field_info {
|
|||
ushort name_index;
|
||||
ushort descriptor_index;
|
||||
ushort attributes_count;
|
||||
attribute_info attributes[attributes_count];
|
||||
@NumElements!attributes_count attribute_info[] attributes;
|
||||
}
|
||||
|
||||
struct method_info {
|
||||
@BigEndian:
|
||||
ushort access_flags;
|
||||
ushort name_index;
|
||||
ushort descriptor_index;
|
||||
ushort attributes_count;
|
||||
attribute_info attributes[attributes_count];
|
||||
@NumElements!attributes_count attribute_info[] attributes;
|
||||
|
||||
enum ACC_PUBLIC = 0x0001;
|
||||
enum ACC_PRIVATE = 0x0002;
|
||||
|
@ -260,12 +340,14 @@ struct method_info {
|
|||
}
|
||||
|
||||
struct attribute_info {
|
||||
@BigEndian:
|
||||
ushort attribute_name_index;
|
||||
uint attribute_length;
|
||||
ubyte[attribute_length] info;
|
||||
@NumBytes!attribute_length ubyte[] info;
|
||||
}
|
||||
|
||||
struct ClassFile {
|
||||
@BigEndian:
|
||||
|
||||
|
||||
enum ACC_PUBLIC = 0x0001;
|
||||
|
@ -277,27 +359,58 @@ struct ClassFile {
|
|||
enum ACC_ANNOTATION = 0x2000;
|
||||
enum ACC_ENUM = 0x4000;
|
||||
|
||||
const(char)[] className() {
|
||||
return this.constant(this.constant(this.this_class).info.class_info.name_index).info.utf8_info.bytes;
|
||||
}
|
||||
|
||||
uint magic;
|
||||
const(char)[] superclassName() {
|
||||
return this.constant(this.constant(this.super_class).info.class_info.name_index).info.utf8_info.bytes;
|
||||
}
|
||||
|
||||
Method[] methodsListing() {
|
||||
Method[] ms;
|
||||
foreach(met; this.methods) {
|
||||
Method m;
|
||||
m.name = this.constant(met.name_index).info.utf8_info.bytes;
|
||||
m.signature = this.constant(met.descriptor_index).info.utf8_info.bytes;
|
||||
m.flags = met.access_flags;
|
||||
ms ~= m;
|
||||
}
|
||||
return ms;
|
||||
}
|
||||
|
||||
static struct Method {
|
||||
const(char)[] name;
|
||||
const(char)[] signature;
|
||||
ushort flags;
|
||||
}
|
||||
|
||||
|
||||
@MustBe(0xcafebabe) uint magic;
|
||||
ushort minor_version;
|
||||
ushort major_version;
|
||||
ushort constant_pool_count;
|
||||
cp_info constant_pool[constant_pool_count-1];
|
||||
ushort constant_pool_count_;
|
||||
// the zeroth item of the constant pool is null, but not actually in the file.
|
||||
ushort constant_pool_count() { return cast(ushort)(constant_pool_count_ - 1); }
|
||||
auto constant(ushort number) {
|
||||
if(number == 0) throw new Exception("invalid");
|
||||
return constant_pool[number - 1];
|
||||
}
|
||||
@NumElements!constant_pool_count cp_info[] constant_pool;
|
||||
ushort access_flags;
|
||||
ushort this_class;
|
||||
ushort super_class;
|
||||
ushort interfaces_count;
|
||||
ushort interfaces[interfaces_count];
|
||||
@NumElements!interfaces_count ushort[] interfaces;
|
||||
ushort fields_count;
|
||||
field_info fields[fields_count];
|
||||
@NumElements!fields_count field_info[] fields;
|
||||
ushort methods_count;
|
||||
method_info methods[methods_count];
|
||||
@NumElements!methods_count method_info[] methods;
|
||||
ushort attributes_count;
|
||||
attribute_info attributes[attributes_count];
|
||||
@NumElements!attributes_count attribute_info[] attributes;
|
||||
}
|
||||
|
||||
/+ } end java class file definitions +/
|
||||
+/
|
||||
|
||||
// semi-FIXME: java.lang.CharSequence is the interface for String. We should support that just as well.
|
||||
// possibly other boxed types too, like Integer.
|
||||
|
@ -560,6 +673,10 @@ private enum ImportImplementationString = q{
|
|||
auto ret = (*env).CallSTATICIntMethod(env, jobj, _jmethodID, DDataToJni(env, args).args);
|
||||
exceptionCheck(env);
|
||||
return ret;
|
||||
} else static if(is(typeof(return) : IJavaObject)) {
|
||||
auto ret = (*env).CallSTATICObjectMethod(env, jobj, _jmethodID, DDataToJni(env, args).args);
|
||||
exceptionCheck(env);
|
||||
return typeof(return).fromExistingJavaObject(ret);
|
||||
} else static if(is(typeof(return) == long)) {
|
||||
auto ret = (*env).CallSTATICLongMethod(env, jobj, _jmethodID, DDataToJni(env, args).args);
|
||||
exceptionCheck(env);
|
||||
|
@ -1085,6 +1202,15 @@ class JavaClass(string javaPackage, CRTP) : IJavaObject {
|
|||
enum Import; /// UDA to indicate you are importing the method from Java. Do NOT put a body on these methods.
|
||||
enum Export; /// UDA to indicate you are exporting the method to Java. Put a D implementation body on these.
|
||||
|
||||
static CRTP fromExistingJavaObject(jobject o) {
|
||||
import core.memory;
|
||||
auto ptr = GC.malloc(__traits(classInstanceSize, CRTP));
|
||||
ptr[0 .. __traits(classInstanceSize, CRTP)] = typeid(CRTP).initializer[];
|
||||
auto obj = cast(CRTP) ptr;
|
||||
obj.internalJavaHandle_ = o;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/+
|
||||
/++
|
||||
D constructors on Java objects don't work right, so this is disabled to ensure
|
||||
|
@ -1120,8 +1246,20 @@ class JavaClass(string javaPackage, CRTP) : IJavaObject {
|
|||
|
||||
import core.stdc.stdio;
|
||||
auto internalJavaClassHandle_ = (*env).FindClass(env, (_javaParameterString[1 .. $-1] ~ "\0").ptr);
|
||||
|
||||
/+
|
||||
if(!internalJavaClassHandle_) {
|
||||
fprintf(stderr, ("Cannot find Java class for " ~ CRTP.stringof));
|
||||
static if(CRTP.stringof == "ssTest2") {
|
||||
import std.file;
|
||||
auto bytes = cast(byte[]) read("Test2.class");
|
||||
auto loader = ClassLoader.getSystemClassLoader().getJavaHandle();
|
||||
internalJavaClassHandle_ = (*env).DefineClass(env, "wtf/Test2", loader, bytes.ptr, cast(int) bytes.length);
|
||||
}
|
||||
}
|
||||
+/
|
||||
|
||||
if(!internalJavaClassHandle_) {
|
||||
fprintf(stderr, ("Cannot find Java class for " ~ CRTP.stringof ~ "\n"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1146,6 +1284,12 @@ class JavaClass(string javaPackage, CRTP) : IJavaObject {
|
|||
__gshared /* immutable */ int function(JNIEnv* env)[] classInitializers_;
|
||||
|
||||
|
||||
/+
|
||||
final class ClassLoader : JavaClass!("java.lang", ClassLoader) {
|
||||
@Import static ClassLoader getSystemClassLoader();
|
||||
}
|
||||
+/
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue