diff --git a/README.md b/README.md index c76afbb..e70acea 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ Import as a Gradle dependency: ```groovy dependencies { - implementation("io.github.over-run:marshal:0.1.0-alpha.20-jdk22") + implementation("io.github.over-run:marshal:0.1.0-alpha.21-jdk22") } ``` diff --git a/gradle.properties b/gradle.properties index 49592cf..0dad2fe 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.20-jdk22 +projVersion=0.1.0-alpha.21-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 a1f8887..050776b 100644 --- a/src/main/java/overrun/marshal/Downcall.java +++ b/src/main/java/overrun/marshal/Downcall.java @@ -852,7 +852,8 @@ private static boolean shouldSkip(Method method) { final boolean b = method.getDeclaredAnnotation(Skip.class) != null || Modifier.isStatic(method.getModifiers()) || - method.isSynthetic(); + method.isSynthetic() || + Modifier.isFinal(method.getModifiers()); if (b) { return true; } @@ -996,96 +997,98 @@ private static DowncallData generateData(Map methodD final String entrypoint = methodData.entrypoint(); final Optional optional = lookup.find(entrypoint); - if (optional.isPresent()) { - // function descriptor - final FunctionDescriptor descriptor; - final FunctionDescriptor get = descriptorMap.get(entrypoint); - if (get != null) { - descriptor = get; - } else { - final var returnType = method.getReturnType(); - final boolean returnVoid = returnType == void.class; - final boolean methodByValue = method.getDeclaredAnnotation(ByValue.class) != null; - - // return layout - final MemoryLayout retLayout; - if (!returnVoid) { - final Convert convert = method.getDeclaredAnnotation(Convert.class); - if (convert != null && returnType == boolean.class) { - retLayout = convert.value().layout(); - } else if (returnType.isPrimitive()) { - retLayout = getValueLayout(returnType); - } else { - final SizedSeg sizedSeg = method.getDeclaredAnnotation(SizedSeg.class); - final Sized sized = method.getDeclaredAnnotation(Sized.class); - final boolean isSizedSeg = sizedSeg != null; - final boolean isSized = sized != null; - if (Struct.class.isAssignableFrom(returnType)) { - StructLayout structLayout = null; - for (Field field : returnType.getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers()) && field.getType() == StructLayout.class) { - try { - structLayout = (StructLayout) field.get(null); - break; - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } + // function descriptor + final FunctionDescriptor descriptor; + final FunctionDescriptor get = descriptorMap.get(entrypoint); + if (get != null) { + descriptor = get; + } else { + final var returnType = method.getReturnType(); + final boolean returnVoid = returnType == void.class; + final boolean methodByValue = method.getDeclaredAnnotation(ByValue.class) != null; + + // return layout + final MemoryLayout retLayout; + if (!returnVoid) { + final Convert convert = method.getDeclaredAnnotation(Convert.class); + if (convert != null && returnType == boolean.class) { + retLayout = convert.value().layout(); + } else if (returnType.isPrimitive()) { + retLayout = getValueLayout(returnType); + } else { + final SizedSeg sizedSeg = method.getDeclaredAnnotation(SizedSeg.class); + final Sized sized = method.getDeclaredAnnotation(Sized.class); + final boolean isSizedSeg = sizedSeg != null; + final boolean isSized = sized != null; + if (Struct.class.isAssignableFrom(returnType)) { + StructLayout structLayout = null; + for (Field field : returnType.getDeclaredFields()) { + if (Modifier.isStatic(field.getModifiers()) && field.getType() == StructLayout.class) { + try { + structLayout = (StructLayout) field.get(null); + break; + } catch (IllegalAccessException e) { + throw new RuntimeException(e); } } - Objects.requireNonNull(structLayout); - if (methodByValue) { - retLayout = structLayout; + } + Objects.requireNonNull(structLayout); + if (methodByValue) { + retLayout = structLayout; + } else { + final MemoryLayout targetLayout; + if (isSizedSeg) { + targetLayout = MemoryLayout.sequenceLayout(sizedSeg.value(), structLayout); + } else if (isSized) { + targetLayout = MemoryLayout.sequenceLayout(sized.value(), structLayout); } else { - final MemoryLayout targetLayout; - if (isSizedSeg) { - targetLayout = MemoryLayout.sequenceLayout(sizedSeg.value(), structLayout); - } else if (isSized) { - targetLayout = MemoryLayout.sequenceLayout(sized.value(), structLayout); - } else { - targetLayout = structLayout; - } - retLayout = ValueLayout.ADDRESS.withTargetLayout(targetLayout); + targetLayout = structLayout; } - } else { - final ValueLayout valueLayout = getValueLayout(returnType); - if ((valueLayout instanceof AddressLayout addressLayout) && (isSizedSeg || isSized)) { - if (isSizedSeg) { - retLayout = addressLayout.withTargetLayout(MemoryLayout.sequenceLayout(sizedSeg.value(), - ValueLayout.JAVA_BYTE)); - } else { - retLayout = addressLayout.withTargetLayout(MemoryLayout.sequenceLayout(sized.value(), - returnType.isArray() ? getValueLayout(returnType.getComponentType()) : ValueLayout.JAVA_BYTE)); - } + retLayout = ValueLayout.ADDRESS.withTargetLayout(targetLayout); + } + } else { + final ValueLayout valueLayout = getValueLayout(returnType); + if ((valueLayout instanceof AddressLayout addressLayout) && (isSizedSeg || isSized)) { + if (isSizedSeg) { + retLayout = addressLayout.withTargetLayout(MemoryLayout.sequenceLayout(sizedSeg.value(), + ValueLayout.JAVA_BYTE)); } else { - retLayout = valueLayout; + retLayout = addressLayout.withTargetLayout(MemoryLayout.sequenceLayout(sized.value(), + returnType.isArray() ? getValueLayout(returnType.getComponentType()) : ValueLayout.JAVA_BYTE)); } + } else { + retLayout = valueLayout; } } - } else { - retLayout = null; } + } else { + retLayout = null; + } - // argument layouts - final var parameters = methodData.parameters(); - final boolean skipFirstParam = methodData.skipFirstParam(); - final int size = skipFirstParam || methodByValue ? - parameters.size() - 1 : - parameters.size(); - final MemoryLayout[] argLayouts = new MemoryLayout[size]; - for (int i = 0; i < size; i++) { - final Parameter parameter = parameters.get(skipFirstParam ? i + 1 : i); - final Class type = parameter.getType(); - final Convert convert = parameter.getDeclaredAnnotation(Convert.class); - if (convert != null && type == boolean.class) { - argLayouts[i] = convert.value().layout(); - } else { - argLayouts[i] = getValueLayout(type); - } + // argument layouts + final var parameters = methodData.parameters(); + final boolean skipFirstParam = methodData.skipFirstParam(); + final int size = skipFirstParam || methodByValue ? + parameters.size() - 1 : + parameters.size(); + final MemoryLayout[] argLayouts = new MemoryLayout[size]; + for (int i = 0; i < size; i++) { + final Parameter parameter = parameters.get(skipFirstParam ? i + 1 : i); + final Class type = parameter.getType(); + final Convert convert = parameter.getDeclaredAnnotation(Convert.class); + if (convert != null && type == boolean.class) { + argLayouts[i] = convert.value().layout(); + } else { + argLayouts[i] = getValueLayout(type); } - - descriptor = returnVoid ? FunctionDescriptor.ofVoid(argLayouts) : FunctionDescriptor.of(retLayout, argLayouts); } + descriptor = returnVoid ? FunctionDescriptor.ofVoid(argLayouts) : FunctionDescriptor.of(retLayout, argLayouts); + } + + descriptorMap1.put(entrypoint, descriptor); + + if (optional.isPresent()) { // linker options final Linker.Option[] options; final Critical critical = method.getDeclaredAnnotation(Critical.class); @@ -1097,13 +1100,11 @@ private static DowncallData generateData(Map methodD if (!map.containsKey(entrypoint)) { map.put(entrypoint, LINKER.downcallHandle(optional.get(), descriptor, options)); - descriptorMap1.put(entrypoint, descriptor); } } else if (method.isDefault()) { map.putIfAbsent(entrypoint, null); - descriptorMap1.put(entrypoint, descriptorMap.get(entrypoint)); } else { - throw new UnsatisfiedLinkError(STR."unresolved symbol: \{entrypoint}: \{methodData.exceptionString()}"); + throw new UnsatisfiedLinkError(STR."unresolved symbol: \{entrypoint} (\{descriptor}): \{methodData.exceptionString()}"); } }); return new DowncallData(Collections.unmodifiableMap(descriptorMap1), Collections.unmodifiableMap(map), lookup);