From 2b048d024a1e9a017a67f215f6dbf4ecf33c1e9a Mon Sep 17 00:00:00 2001 From: squid233 <60126026+squid233@users.noreply.github.com> Date: Thu, 1 Feb 2024 22:49:33 +0800 Subject: [PATCH] Downcall: fix cross-module access --- README.md | 3 +-- gradle.properties | 2 +- src/main/java/overrun/marshal/Downcall.java | 14 ++++++++------ .../overrun/marshal/test/DescriptorMapTest.java | 2 +- .../marshal/test/IndirectInterfaceTest.java | 4 ++-- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a6bfda4..de48e11 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,6 @@ import overrun.marshal.gen.*; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.lang.foreign.SegmentAllocator; -import java.lang.foreign.ValueLayout; /** * GLFW constants and functions @@ -95,6 +94,6 @@ Import as a Gradle dependency: ```groovy dependencies { - implementation("io.github.over-run:marshal:0.1.0-alpha.15-jdk22") + implementation("io.github.over-run:marshal:0.1.0-alpha.16-jdk22") } ``` diff --git a/gradle.properties b/gradle.properties index f1d9b00..b959d67 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ projGroupId=io.github.over-run projArtifactId=marshal # The project name should only contain lowercase letters, numbers and hyphen. projName=marshal -projVersion=0.1.0-alpha.15-jdk22 +projVersion=0.1.0-alpha.16-jdk22 projDesc=Marshaler of native libraries # Uncomment them if you want to publish to maven repository. projUrl=https://github.com/Over-Run/marshal diff --git a/src/main/java/overrun/marshal/Downcall.java b/src/main/java/overrun/marshal/Downcall.java index b271550..4994372 100644 --- a/src/main/java/overrun/marshal/Downcall.java +++ b/src/main/java/overrun/marshal/Downcall.java @@ -46,6 +46,10 @@ *

Loading native library

* You can load native libraries with {@link #load(Class, SymbolLookup)}. * This method generates a hidden class that loads method handle with the given symbol lookup. + *

+ * The generated class implements the target class. + * The target class MUST be {@code public} + * as the generated class is defined in package {@code overrun.marshal}. *

Methods

* The loader finds method from the target class and its superclasses. *

@@ -397,7 +401,7 @@ private static Method findUpcallWrapper(Class aClass) { @SuppressWarnings("unchecked") private static T loadBytecode(Class targetClass, SymbolLookup lookup, Map descriptorMap) { final ClassFile cf = of(); - final ClassDesc cd_thisClass = ClassDesc.of(targetClass.getPackageName(), DEFAULT_NAME); + final ClassDesc cd_thisClass = ClassDesc.of(Downcall.class.getPackageName(), DEFAULT_NAME); final byte[] bytes = cf.build(cd_thisClass, classBuilder -> { final List methodList = Arrays.stream(targetClass.getMethods()) .filter(method -> @@ -420,7 +424,6 @@ private static T loadBytecode(Class targetClass, SymbolLookup lookup, Map }); final Map methodDataMap = LinkedHashMap.newLinkedHashMap(methodList.size()); - final Map handleDataMap = LinkedHashMap.newLinkedHashMap(methodList.size()); classBuilder.withFlags(ACC_FINAL | ACC_SUPER); @@ -454,7 +457,6 @@ private static T loadBytecode(Class targetClass, SymbolLookup lookup, Map ); methodDataMap.put(method, methodData); - handleDataMap.put(method, methodData); classBuilder.withField(handleName, CD_MethodHandle, ACC_PRIVATE | ACC_FINAL); }); @@ -468,7 +470,7 @@ private static T loadBytecode(Class targetClass, SymbolLookup lookup, Map .invokespecial(CD_Object, INIT_NAME, MTD_void); // method handles - handleDataMap.values().forEach(methodData -> { + methodDataMap.values().forEach(methodData -> { // initialize field codeBuilder.aload(codeBuilder.receiverSlot()) .aload(codeBuilder.parameterSlot(0)) @@ -866,7 +868,7 @@ private static T loadBytecode(Class targetClass, SymbolLookup lookup, Map }); // handle loader - handleDataMap.forEach((method, methodData) -> classBuilder.withMethod( + methodDataMap.forEach((method, methodData) -> classBuilder.withMethod( methodData.loaderName(), MTD_MethodHandle_SymbolLookup, ACC_PRIVATE | ACC_STATIC, @@ -1046,7 +1048,7 @@ private static T loadBytecode(Class targetClass, SymbolLookup lookup, Map }); try { - final MethodHandles.Lookup hiddenClass = MethodHandles.privateLookupIn(targetClass, MethodHandles.lookup()) + final MethodHandles.Lookup hiddenClass = MethodHandles.lookup() .defineHiddenClassWithClassData(bytes, Map.copyOf(descriptorMap), true, MethodHandles.Lookup.ClassOption.STRONG); return (T) hiddenClass.findConstructor(hiddenClass.lookupClass(), MethodType.methodType(void.class, SymbolLookup.class)) .invoke(lookup); diff --git a/src/test/java/overrun/marshal/test/DescriptorMapTest.java b/src/test/java/overrun/marshal/test/DescriptorMapTest.java index 4f175fb..81400d9 100644 --- a/src/test/java/overrun/marshal/test/DescriptorMapTest.java +++ b/src/test/java/overrun/marshal/test/DescriptorMapTest.java @@ -87,7 +87,7 @@ static boolean acceptLong(long d) { return d == 84L; } - interface Interface { + public interface Interface { static Interface getInstance(ValueLayout returnLayout, ValueLayout acceptLayout) { return Downcall.load(lookup(returnLayout, acceptLayout), Map.of( "testReturn", FunctionDescriptor.of(returnLayout), diff --git a/src/test/java/overrun/marshal/test/IndirectInterfaceTest.java b/src/test/java/overrun/marshal/test/IndirectInterfaceTest.java index 621fc1d..2d5b8c5 100644 --- a/src/test/java/overrun/marshal/test/IndirectInterfaceTest.java +++ b/src/test/java/overrun/marshal/test/IndirectInterfaceTest.java @@ -29,13 +29,13 @@ * @since 0.1.0 */ public final class IndirectInterfaceTest { - interface I1 { + public interface I1 { default int fun1() { return 1; } } - interface I2 extends I1 { + public interface I2 extends I1 { } I2 INSTANCE = Downcall.load(I2.class, SymbolLookup.loaderLookup());