Skip to content

Commit b5de697

Browse files
committed
Fixes #11 with getting rid of additional layer of type mapping
1 parent 1f95e59 commit b5de697

26 files changed

+482
-407
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package io.github.digitalsmile.gpio.functions;
2+
3+
import io.github.digitalsmile.annotation.NativeMemory;
4+
import io.github.digitalsmile.annotation.function.ByAddress;
5+
import io.github.digitalsmile.annotation.function.NativeFunction;
6+
import io.github.digitalsmile.annotation.function.NativeMemoryException;
7+
import io.github.digitalsmile.annotation.function.Returns;
8+
import io.github.digitalsmile.annotation.structure.NativeMemoryLayout;
9+
10+
@NativeMemory
11+
public interface FunctionTest {
12+
@NativeFunction(name = "ioctl", useErrno = true, returnType = int.class)
13+
int callByValue(int fd, long command, long data) throws NativeMemoryException;
14+
15+
@NativeFunction(name = "ioctl", useErrno = true, returnType = int.class)
16+
long call(int fd, long command, @Returns @ByAddress long data) throws NativeMemoryException;
17+
18+
@NativeFunction(name = "ioctl", useErrno = true, returnType = int.class)
19+
int call(int fd, long command, @Returns @ByAddress int data) throws NativeMemoryException;
20+
21+
@NativeFunction(name = "ioctl", useErrno = true, returnType = int.class)
22+
<T extends NativeMemoryLayout> T call(int fd, long command, @Returns T data) throws NativeMemoryException;
23+
24+
@NativeFunction(name = "open64", useErrno = true, returnType = int.class)
25+
int open(@ByAddress String path, int openFlag) throws NativeMemoryException;
26+
27+
@NativeFunction(name = "close", useErrno = true)
28+
void close(int fd)throws NativeMemoryException;
29+
30+
@NativeFunction(name = "read", useErrno = true, returnType = int.class)
31+
byte[] read(int fd, @Returns @ByAddress byte[] buffer, int size) throws NativeMemoryException;
32+
33+
@NativeFunction(name = "write", useErrno = true, returnType = int.class)
34+
int write(int fd, @ByAddress byte[] data) throws NativeMemoryException;
35+
}

annotation-processor/src/main/java/io/github/digitalsmile/NativeProcessor.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.github.digitalsmile.annotation.function.NativeMemoryException;
1010
import io.github.digitalsmile.annotation.function.Returns;
1111
import io.github.digitalsmile.annotation.structure.Enums;
12+
import io.github.digitalsmile.annotation.structure.NativeMemoryLayout;
1213
import io.github.digitalsmile.annotation.structure.Structs;
1314
import io.github.digitalsmile.annotation.structure.Unions;
1415
import io.github.digitalsmile.composers.EnumComposer;
@@ -17,13 +18,12 @@
1718
import io.github.digitalsmile.functions.FunctionNode;
1819
import io.github.digitalsmile.functions.Library;
1920
import io.github.digitalsmile.functions.ParameterNode;
20-
import io.github.digitalsmile.headers.mapping.ObjectTypeMapping;
21+
import io.github.digitalsmile.headers.Parser;
2122
import io.github.digitalsmile.headers.model.NativeMemoryModel;
2223
import io.github.digitalsmile.headers.model.NativeMemoryNode;
23-
import io.github.digitalsmile.headers.type.ObjectOriginalType;
24-
import io.github.digitalsmile.headers.type.ObjectTypeMirror;
25-
import io.github.digitalsmile.headers.type.OriginalType;
26-
import io.github.digitalsmile.headers.Parser;
24+
import io.github.digitalsmile.headers.mapping.ObjectOriginalType;
25+
import io.github.digitalsmile.headers.mapping.ObjectTypeMirror;
26+
import io.github.digitalsmile.headers.mapping.OriginalType;
2727
import org.openjdk.jextract.Declaration;
2828
import org.openjdk.jextract.JextractTool;
2929
import org.openjdk.jextract.clang.Index;
@@ -38,6 +38,7 @@
3838
import javax.lang.model.element.ExecutableElement;
3939
import javax.lang.model.element.TypeElement;
4040
import javax.lang.model.element.VariableElement;
41+
import javax.lang.model.type.TypeKind;
4142
import javax.tools.Diagnostic;
4243
import javax.tools.FileObject;
4344
import javax.tools.StandardLocation;
@@ -107,26 +108,14 @@ private void processHeaderFiles(Element element, String[] headerFiles, String pa
107108
List<Type> structs = null;
108109
if (structsAnnotation != null) {
109110
structs = Arrays.stream(structsAnnotation.value()).map(struct -> new Type(struct.name(), struct.javaName())).toList();
110-
Arrays.stream(structsAnnotation.value()).forEach(struct -> {
111-
PrettyName.addName(struct.name(), struct.javaName());
112-
OriginalType.register(new ObjectTypeMapping(struct.name()));
113-
});
114111
}
115112
List<Type> enums = null;
116113
if (enumsAnnotation != null) {
117114
enums = Arrays.stream(enumsAnnotation.value()).map(enoom -> new Type(enoom.name(), enoom.javaName())).toList();
118-
Arrays.stream(enumsAnnotation.value()).forEach(enoom -> {
119-
PrettyName.addName(enoom.name(), enoom.javaName());
120-
OriginalType.register(new ObjectTypeMapping(enoom.name()));
121-
});
122115
}
123116
List<Type> unions = null;
124117
if (unionsAnnotation != null) {
125118
unions = Arrays.stream(unionsAnnotation.value()).map(union -> new Type(union.name(), union.javaName())).toList();
126-
Arrays.stream(unionsAnnotation.value()).forEach(union -> {
127-
PrettyName.addName(union.name(), union.javaName());
128-
OriginalType.register(new ObjectTypeMapping(union.name()));
129-
});
130119
}
131120

132121
boolean rootConstants = false;
@@ -217,14 +206,19 @@ private void processFunctions(Element rootElement, List<Element> functionElement
217206
break;
218207
}
219208
List<ParameterNode> parameters = new ArrayList<>();
220-
var returnType = OriginalType.of(functionElement.getReturnType());
209+
210+
var returnType = getBoundsOriginalType(functionElement);
211+
if (returnType == null) {
212+
return;
213+
}
221214
var nativeReturnType = OriginalType.of(instance.returnType() != null ? instance.returnType() : new ObjectTypeMirror());
222215
for (VariableElement variableElement : functionElement.getParameters()) {
223216
var returns = variableElement.getAnnotation(Returns.class);
224217
var byAddress = variableElement.getAnnotation(ByAddress.class);
225-
var type = OriginalType.of(variableElement.asType());
218+
var type = variableElement.asType();
219+
var originalType = type.getKind().equals(TypeKind.TYPEVAR) ? returnType : OriginalType.of(type);
226220
var parameterNode = new ParameterNode(variableElement.getSimpleName().toString(),
227-
type, returns != null, byAddress != null || type instanceof ObjectOriginalType);
221+
originalType, returns != null, byAddress != null || originalType instanceof ObjectOriginalType);
228222
parameters.add(parameterNode);
229223
}
230224

@@ -241,6 +235,21 @@ private void processFunctions(Element rootElement, List<Element> functionElement
241235
createGeneratedFile(packageName, nativeClassJavaName, output);
242236
}
243237

238+
private OriginalType getBoundsOriginalType(ExecutableElement functionElement) {
239+
var methodRealTypes = functionElement.getTypeParameters().stream().findFirst().orElse(null);
240+
if (methodRealTypes != null) {
241+
var boundsType = methodRealTypes.getBounds().stream().findFirst().orElse(null);
242+
if (boundsType == null || !boundsType.toString().equals(NativeMemoryLayout.class.getName())) {
243+
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Parameter with object definition should extend NativeMemoryLayout interface", functionElement);
244+
return null;
245+
} else {
246+
return OriginalType.of(boundsType);
247+
}
248+
} else {
249+
return OriginalType.of(functionElement.getReturnType());
250+
}
251+
}
252+
244253
private FileObject tmpFile;
245254

246255
private List<Path> getHeaderPaths(String[] headerFiles) {

annotation-processor/src/main/java/io/github/digitalsmile/composers/EnumComposer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import com.squareup.javapoet.JavaFile;
55
import com.squareup.javapoet.MethodSpec;
66
import com.squareup.javapoet.TypeSpec;
7-
import io.github.digitalsmile.headers.mapping.PrimitiveTypeMapping;
87
import io.github.digitalsmile.headers.model.NativeMemoryNode;
8+
import io.github.digitalsmile.headers.mapping.PrimitiveOriginalType;
99

1010
import javax.annotation.processing.Messager;
1111
import javax.lang.model.element.Modifier;
@@ -26,7 +26,7 @@ public String compose(String packageName, String prettyName, NativeMemoryNode pa
2626
.addModifiers(Modifier.PUBLIC)
2727
.addJavadoc("Source: $L", parentNode.getSource());
2828
for (NativeMemoryNode node : parentNode.nodes()) {
29-
var type = (PrimitiveTypeMapping) node.getType().typeMapping();
29+
var type = (PrimitiveOriginalType) node.getType();
3030
var fieldSpec = FieldSpec.builder(type.valueLayout().carrier(), node.getName(), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
3131
.initializer("$L$L", node.getValue(), type.literal())
3232
.addJavadoc("Source: $L", node.getSource())
@@ -36,7 +36,7 @@ public String compose(String packageName, String prettyName, NativeMemoryNode pa
3636
var outputFile = JavaFile.builder(packageName, classBuilder.build()).indent("\t").skipJavaLangImports(true).build();
3737
return outputFile.toString();
3838
} else {
39-
var type = (PrimitiveTypeMapping) parentNode.nodes().getFirst().getType().typeMapping();
39+
var type = (PrimitiveOriginalType) parentNode.nodes().getFirst().getType();
4040
var enumBuilder = TypeSpec.enumBuilder(prettyName)
4141
.addModifiers(Modifier.PUBLIC)
4242
.addJavadoc("Source: $L", parentNode.getSource());

annotation-processor/src/main/java/io/github/digitalsmile/composers/FunctionComposer.java

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package io.github.digitalsmile.composers;
22

33
import com.squareup.javapoet.*;
4-
import io.github.digitalsmile.functions.Library;
54
import io.github.digitalsmile.PrettyName;
65
import io.github.digitalsmile.annotation.function.NativeCall;
76
import io.github.digitalsmile.annotation.function.NativeMemoryException;
7+
import io.github.digitalsmile.annotation.structure.NativeMemoryLayout;
88
import io.github.digitalsmile.functions.FunctionNode;
9+
import io.github.digitalsmile.functions.Library;
910
import io.github.digitalsmile.functions.ParameterNode;
10-
import io.github.digitalsmile.headers.mapping.DeferredObjectTypeMapping;
11-
import io.github.digitalsmile.headers.mapping.ObjectTypeMapping;
12-
import io.github.digitalsmile.headers.mapping.PrimitiveTypeMapping;
13-
import io.github.digitalsmile.headers.type.ArrayOriginalType;
14-
import io.github.digitalsmile.headers.type.ObjectOriginalType;
15-
import io.github.digitalsmile.headers.type.PrimitiveOriginalType;
11+
import io.github.digitalsmile.headers.mapping.ArrayOriginalType;
12+
import io.github.digitalsmile.headers.mapping.ObjectOriginalType;
13+
import io.github.digitalsmile.headers.mapping.PrimitiveOriginalType;
1614

1715
import javax.annotation.processing.Messager;
1816
import javax.lang.model.element.ExecutableElement;
@@ -66,12 +64,12 @@ public String compose(String packageName, String originalName, String javaName,
6664
for (FunctionNode functionNode : nodes) {
6765
var returnsCodeBlock = CodeBlock.builder();
6866
List<CodeBlock> parameters = new ArrayList<>();
69-
var nativeReturnTypeMapping = functionNode.nativeReturnType().typeMapping();
67+
var nativeReturnTypeMapping = functionNode.nativeReturnType();
7068
if (!nativeReturnTypeMapping.carrierClass().equals(void.class)) {
7169
switch (nativeReturnTypeMapping) {
72-
case PrimitiveTypeMapping primitiveTypeMapping ->
70+
case PrimitiveOriginalType primitiveTypeMapping ->
7371
parameters.add(CodeBlock.builder().add("$T.$L", ValueLayout.class, primitiveTypeMapping.valueLayoutName()).build());
74-
case ObjectTypeMapping _, DeferredObjectTypeMapping _ ->
72+
case ObjectOriginalType _, ArrayOriginalType _ ->
7573
parameters.add(CodeBlock.builder().add("$T.ADDRESS", ValueLayout.class).build());
7674
default -> throw new IllegalStateException("Unexpected value: " + nativeReturnTypeMapping);
7775
}
@@ -80,7 +78,7 @@ public String compose(String packageName, String originalName, String javaName,
8078
var methodBody = CodeBlock.builder();
8179
for (ParameterNode parameterNode : functionNode.functionParameters()) {
8280
var prettyName = PrettyName.getVariableName(parameterNode.name());
83-
var parameterTypeMapping = parameterNode.typeMapping().typeMapping();
81+
var parameterTypeMapping = parameterNode.typeMapping();
8482
if (parameterNode.byAddress()) {
8583
parameters.add(CodeBlock.builder().add("$T.ADDRESS", ValueLayout.class).build());
8684
arguments.add(CodeBlock.builder().add("$LMemorySegment", prettyName).build());
@@ -107,7 +105,7 @@ public String compose(String packageName, String originalName, String javaName,
107105
}
108106
} else {
109107
parameters.add(CodeBlock.builder().add("$T.$L", ValueLayout.class, parameterTypeMapping.valueLayoutName()).build());
110-
if (parameterTypeMapping instanceof ObjectTypeMapping) {
108+
if (parameterTypeMapping instanceof ObjectOriginalType) {
111109
arguments.add(CodeBlock.builder().add("$LMemorySegment", prettyName).build());
112110
} else {
113111
arguments.add(CodeBlock.builder().add("$L", prettyName).build());
@@ -122,6 +120,8 @@ public String compose(String packageName, String originalName, String javaName,
122120
case ObjectOriginalType _ -> {
123121
if (parameterTypeMapping.carrierClass().equals(String.class)) {
124122
returnsCodeBlock.addStatement("return $LMemorySegment.getString(0)", prettyName);
123+
} else if (parameterTypeMapping.carrierClass().equals(NativeMemoryLayout.class)) {
124+
returnsCodeBlock.addStatement("return $L.fromBytes($LMemorySegment)", prettyName, prettyName);
125125
} else {
126126
returnsCodeBlock.addStatement("return $L.createEmpty().fromBytes($LMemorySegment)", PrettyName.getObjectName(functionNode.returnType().typeName()), prettyName);
127127
}
@@ -158,18 +158,32 @@ public String compose(String packageName, String originalName, String javaName,
158158
methodBody.addStatement("$L.invoke($L)", nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
159159
methodBody.addStatement("processError(capturedState, $S, $L)", methodsMap.get(functionNode), CodeBlock.join(arguments, ", "));
160160
} else {
161-
methodBody.addStatement("var callResult = ($T) $L.invoke($L)",
162-
nativeReturnTypeMapping.carrierClass().equals(Object.class) ? MemorySegment.class : nativeReturnTypeMapping.carrierClass(),
163-
nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
161+
switch (functionNode.nativeReturnType()) {
162+
case ArrayOriginalType _, ObjectOriginalType _ ->
163+
methodBody.addStatement("var callResult = ($T) $L.invoke($L)",
164+
MemorySegment.class,
165+
nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
166+
default ->
167+
methodBody.addStatement("var callResult = ($T) $L.invoke($L)",
168+
nativeReturnTypeMapping.carrierClass(),
169+
nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
170+
}
164171
methodBody.addStatement("processError(callResult, capturedState, $S, $L)", methodsMap.get(functionNode), CodeBlock.join(arguments, ", "));
165172
}
166173
} else {
167174
if (nativeReturnTypeMapping.carrierClass().equals(void.class)) {
168175
methodBody.addStatement("$L.invoke($L)", nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
169176
} else {
170-
methodBody.addStatement("var callResult = ($T) $L.invoke($L)",
171-
nativeReturnTypeMapping.carrierClass().equals(Object.class) ? MemorySegment.class : nativeReturnTypeMapping.carrierClass(),
172-
nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
177+
switch (functionNode.nativeReturnType()) {
178+
case ArrayOriginalType _, ObjectOriginalType _ ->
179+
methodBody.addStatement("var callResult = ($T) $L.invoke($L)",
180+
MemorySegment.class,
181+
nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
182+
default ->
183+
methodBody.addStatement("var callResult = ($T) $L.invoke($L)",
184+
nativeReturnTypeMapping.carrierClass(),
185+
nameMapper.get(functionNode), CodeBlock.join(arguments, ", "));
186+
}
173187
}
174188
}
175189

0 commit comments

Comments
 (0)