Skip to content

Commit

Permalink
Merge pull request #1 from Over-Run/rewrite
Browse files Browse the repository at this point in the history
Rewrite
  • Loading branch information
squid233 authored Dec 10, 2023
2 parents eeae5fe + 5911cd1 commit d09f3a5
Show file tree
Hide file tree
Showing 25 changed files with 2,052 additions and 623 deletions.
101 changes: 75 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,107 @@ Marshal allows you to conveniently create native library bindings with [FFM API]

See [wiki](https://github.com/Over-Run/marshal/wiki) for more information.

This library requires JDK 22 or newer.

## Overview

```java
import overrun.marshal.*;

import java.lang.foreign.MemorySegment;

/**
* GLFW constants and functions
* <p>
* The documentation will be automatically copied
* into the generated file
*/
@NativeApi(libname = "libglfw.so", name = "GLFW")
interface CGLFW {
@Doc("""
A field""")
/**
* A field
*/
int GLFW_KEY_A = 65;

@Doc("""
Sets swap interval.
<p>
You can set the access modifier.
@param interval the interval""")
/**
* Sets the swap interval.
* <p>
* You can set the access modifier.
*
* @param interval the interval
*/
@Access(AccessModifier.PROTECTED)
void glfwSwapInterval(int interval);

@Doc("""
Custom method body""")
/**
* Custom method body
*/
@Custom("""
glfwSwapInterval(1);""")
void glfwEnableVSync();

@Doc("""
{@return default value if the function was not found}""")
/**
* {@return default value if the function was not found}
*/
@Default("0")
@Entrypoint("glfwGetTime")
double getTime();

@Doc("""
Fixed size array.
Note: this method doesn't exist in GLFW""")
/**
* Fixed size array.
* Note: this method doesn't exist in GLFW
*
* @param arr The array
*/
void fixedSizeArray(@FixedSize(2) int[] arr);

@Doc("""
A simple method""")
void glfwSetWindowPos(MemorySegment window, MemorySegment posX, MemorySegment posY);

@Doc("""
Overload""")
/**
* A simple method
* <p>
* Note: annotation Ref in this method is unnecessary;
* however, you can use it to mark
*
* @param window the window
* @param posX the position x
* @param posY the position y
*/
void glfwSetWindowPos(MemorySegment window, @Ref MemorySegment posX, @Ref MemorySegment posY);

/**
* Overload another method with the same name
*
* @param window the window
* @param posX the array where to store the position x
* @param posY the array where to store the position y
*/
@Overload
void glfwSetWindowPos(MemorySegment window, @Ref int[] posX, @Ref int[] posY);

/**
* {@return a UTF-16 string}
*/
@SetCharset("UTF-16")
String returnString();
}

class Main {
public static void main(String[] args) {
int key = GLFW.GLFW_KEY_A;
GLFW.glfwSwapInterval(1);
GLFW.glfwEnableVSync();
double time = GLFW.getTime();
GLFW.fixedSizeArray(new int[]{4, 2});
MemorySegment windowHandle = /*...*/createWindow();
try (MemoryStack stack = /*...*/stackPush()) {
MemorySegment bufX1 = stack.callocInt(1);
MemorySegment bufY1 = stack.callocInt(1);
int[] bufX2 = {0};
int[] bufY2 = {0};
GLFW.glfwSetWindowPos(windowHandle, bufX1, bufY1);
GLFW.glfwSetWindowPos(windowHandle, bufX2, bufY2);
}
String s = GLFW.returnString();
}
}
```

Expand All @@ -67,8 +121,3 @@ dependencies {
implementation("io.github.over-run:marshal:$marshalVersion")
}
```

## Compiler Arguments

You can disable the warning of marshalling boolean arrays
by using the compiler argument `-Aoverrun.marshal.disableBoolArrayWarn=true`.
41 changes: 26 additions & 15 deletions demo/src/main/java/overrun/marshal/test/CMarshalTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,30 @@
import java.lang.foreign.MemorySegment;

/**
* Test basic features
*
* @author squid233
* @since 0.1.0
*/
@NativeApi(libname = "NativeLib.dll", name = "MarshalTest", makeFinal = false)
public interface CMarshalTest {
int CONST_VALUE = 42;
boolean BOOL_VALUE = true;
@Doc("""
A string value""")
/**
* A string value
*/
String STR_VALUE = "Hello world";

void test();

@Entrypoint("test")
void testWithEntrypoint();

@Doc("""
This is a test method with javadoc.
@return an integer
""")
/**
* This is a test method with javadoc.
*
* @return an integer
*/
int testWithDocAndReturnValue();

int testWithReturnValue();
Expand All @@ -65,7 +68,7 @@ public interface CMarshalTest {
@Overload
void testWithArray(int[] arr);

void testWithOneRef(MemorySegment arr);
void testWithOneRef(@Ref MemorySegment arr);

@Overload
void testWithOneRef(@Ref int[] arr);
Expand All @@ -75,17 +78,24 @@ public interface CMarshalTest {
@Overload
void testWithRefArray(int[] arr0, @Ref int[] arr1, @Ref(nullable = true) int[] arr2, boolean[] arr3, @Ref boolean[] arr4, @FixedSize(3) int[] arr5);

void testWithString(MemorySegment str);
void testWithString(MemorySegment str1, MemorySegment str2);

@Overload
void testWithString(String str);
void testWithString(String str1, @SetCharset("UTF-16") String str2);

@Entrypoint("testReturnString")
MemorySegment ntestReturnString();

@Overload("ntestReturnString")
String testReturnString();

@Entrypoint("testReturnStringUTF16")
MemorySegment ntestReturnStringUTF16();

@Overload("ntestReturnStringUTF16")
@SetCharset("UTF-16")
String testReturnStringUTF16();

MemorySegment testStringArray(MemorySegment arr, MemorySegment refArr);

@Overload
Expand All @@ -102,11 +112,12 @@ public interface CMarshalTest {
@Overload
void testMixArrSeg(MemorySegment segment, @Ref int[] arr);

@Doc("""
This is a test that tests all features.
@param segment A memory segment
@return Another memory segment""")
/**
* This is a test that tests all features.
*
* @param segment A memory segment
* @return Another memory segment
*/
@Access(AccessModifier.PROTECTED)
@Default("MemorySegment.NULL")
@Entrypoint("testAllFeatures")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
import java.lang.foreign.MemorySegment;

/**
* Test with loader
*
* @author squid233
* @since 0.1.0
*/
@NativeApi(libname = "NativeLib", name = "MarshalTestWithSelector", selector = NativeLibSelector.class)
public interface CMarshalTestWithSelector {
@NativeApi(libname = "NativeLib", name = "MarshalTestWithLoader", loader = NativeLibLoader.class)
public interface CMarshalTestWithLoader {
MemorySegment testWithArgAndReturnValue(MemorySegment segment);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,20 @@
* copies or substantial portions of the Software.
*/

package overrun.marshal;
package overrun.marshal.test;

import overrun.marshal.LibraryLoader;

import java.lang.foreign.Arena;
import java.lang.foreign.SymbolLookup;

/**
* A library selector.
*
* @author squid233
* @see NativeApi
* @since 0.1.0
*/
public interface LibrarySelector {
/**
* Selects the library based on the basename and the operating system.
*
* @param basename the basename of the native library
* @return the final path of the library
*/
String select(String basename);
public final class NativeLibLoader implements LibraryLoader {
@Override
public SymbolLookup load(String basename) {
return SymbolLookup.libraryLookup(basename, Arena.ofAuto());
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ projArtifactId=marshal
# The project name should only contain lowercase letters, numbers and hyphen.
projName=marshal
projVersion=0.1.0-alpha.0
projDesc=Marshaller of native libraries
projDesc=Marshaler of native libraries
# Uncomment them if you want to publish to maven repository.
projUrl=https://github.com/Over-Run/marshal
projLicenseUrl=https://raw.githubusercontent.com/Over-Run/marshal/main/LICENSE
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/overrun/marshal/AccessModifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package overrun.marshal;

/**
* The access modifier of a method.
* The access modifier.
*
* @author squid233
* @see Access
Expand Down
66 changes: 66 additions & 0 deletions src/main/java/overrun/marshal/LibraryLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* MIT License
*
* Copyright (c) 2023 Overrun Organization
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*/

package overrun.marshal;

import java.lang.foreign.Arena;
import java.lang.foreign.SymbolLookup;

/**
* A library loader.
*
* @author squid233
* @see NativeApi
* @since 0.1.0
*/
public interface LibraryLoader {
/**
* Creates a library lookup with the given name.
*
* @param name the name of the native library
* @return the symbol lookup of the library
*/
static SymbolLookup loadLibrary(String name) {
return SymbolLookup.libraryLookup(name, Arena.global());
}

/**
* Loads a library based on the basename and the operating system.
*
* @param basename the basename of the native library
* @return the symbol lookup of the library
*/
SymbolLookup load(String basename);

/**
* The default library loader.
*
* @author squid233
* @since 0.1.0
*/
final class Default implements LibraryLoader {
/**
* Creates the default library loader.
*/
public Default() {
}

@Override
public SymbolLookup load(String basename) {
return SymbolLookup.libraryLookup(basename, Arena.global());
}
}
}
Loading

0 comments on commit d09f3a5

Please sign in to comment.