Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proof of concept helper binding generation #22

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .run/Generate helpers.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Generate helpers" type="JetRunConfigurationType">
<option name="MAIN_CLASS_NAME" value="vipsffm.GenerateHelpers" />
<module name="vips-ffm.helper-generator.main" />
<shortenClasspath name="NONE" />
<option name="VM_PARAMETERS" value="--enable-preview" />
<method v="2">
<option name="Gradle.BeforeRunTask" enabled="true" tasks="compileJava" externalProjectPath="$PROJECT_DIR$/core" vmOptions="" scriptParameters="" />
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
plugins {
kotlin("jvm") version "2.0.10" apply false
}
48 changes: 48 additions & 0 deletions core/src/main/java/app/photofox/vipsffm/helper/VipsInvoker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package app.photofox.vipsffm.helper;

import app.photofox.vipsffm.generated.VipsRaw;

import java.lang.foreign.Arena;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class VipsInvoker {

public static MemoryLayout[] makeInvokerVarargLayouts(VipsOption... args) {
List<ValueLayout> layouts = new ArrayList<>();
var listArgs = Arrays.stream(args).toList();
listArgs.forEach((arg) -> {
layouts.add(VipsRaw.C_POINTER);
switch (arg) {
case VipsStringOption _ -> layouts.add(VipsRaw.C_POINTER);
case VipsIntOption _ -> layouts.add(VipsRaw.C_INT);
}
});
layouts.add(VipsRaw.C_POINTER);
return layouts.toArray(MemoryLayout[]::new);
}

public static Object[] makeInvokerVarargObjects(Arena arena, VipsOption... args) {
var invokeArgs = new ArrayList<>();
var listArgs = Arrays.stream(args).toList();
listArgs.forEach((arg) -> {
var keyCString = arena.allocateFrom(arg.key());
invokeArgs.add(keyCString);
switch (arg) {
case VipsStringOption stringOption -> {
var valueCString = arena.allocateFrom(stringOption.value());
invokeArgs.add(valueCString);
}
case VipsIntOption intOption -> {
invokeArgs.add(intOption.value());
}
}
});
invokeArgs.add(MemorySegment.NULL);
return invokeArgs.toArray(Object[]::new);
}
}
40 changes: 40 additions & 0 deletions core/src/main/java/app/photofox/vipsffm/helper/VipsValidation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package app.photofox.vipsffm.helper;

import app.photofox.vipsffm.generated.VipsRaw;

import java.lang.foreign.*;

public class VipsValidation {

public static boolean isValidPointer(MemorySegment memorySegment) {
return memorySegment != MemorySegment.NULL && memorySegment.address() != 0;
}

public static boolean isValidResult(int result) {
return result == 0;
}

public static void throwVipsError(String commandName) throws VipsError {
var errorBuffer = VipsRaw.vips_error_buffer();
if (!isValidPointer(errorBuffer)) {
throw new VipsError("failed to run vips command " + commandName);
}

var errorString = errorBuffer.getString(0);
throw new VipsError("failed to run vips command " + commandName + ": " + errorString);
}

public static void throwInvalidInputError(String commandName, String argName) throws VipsError {
throw new VipsError("invalid input provided to command " + commandName + " argument " + argName);
}

public static void throwInvalidOutputError(String commandName, String argName) throws VipsError {
var errorBuffer = VipsRaw.vips_error_buffer();
if (!isValidPointer(errorBuffer)) {
throw new VipsError("failed to run vips command " + commandName);
}

var errorString = errorBuffer.getString(0);
throw new VipsError("invalid output pointer from command " + commandName + " argument " + argName + ": " + errorString);
}
}
2 changes: 2 additions & 0 deletions generate_ffm_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,5 @@ set -x
--library "vips" \
@includes_filtered.txt \
"$LIBVIPS_ENTRY_PATH"

./gradlew clean helper-generator:run
50 changes: 50 additions & 0 deletions helper-generator/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@file:Suppress("UnstableApiUsage")

import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent

plugins {
kotlin("jvm")
application
}

repositories {
mavenCentral()
}

dependencies {
implementation(project(":core"))
implementation(platform("org.slf4j:slf4j-bom:2.0.16"))
implementation("com.squareup:javapoet:1.13.0")
implementation("org.slf4j:slf4j-api")
implementation("org.slf4j:slf4j-simple")
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(22))
}
}

testing {
suites {
val test by getting(JvmTestSuite::class) {
useKotlinTest("2.0.0")
testType = TestSuiteType.UNIT_TEST
}
}
}

tasks.withType<Test> {
testLogging {
events = TestLogEvent.values().toSet() - TestLogEvent.STARTED
exceptionFormat = TestExceptionFormat.FULL
}
outputs.upToDateWhen { false }
}

application {
mainClass = "vipsffm.GenerateHelpers"
applicationDefaultJvmArgs = listOf("--enable-preview")
tasks.run.get().workingDir = rootProject.projectDir
}
Loading