Move library loading interop to a java class
This commit is contained in:
parent
ad2c3d3606
commit
1fe9d2cb02
4 changed files with 59 additions and 6 deletions
12
build.clj
12
build.clj
|
|
@ -19,7 +19,8 @@
|
||||||
(def lib-coord 'org.suskalo/coffi)
|
(def lib-coord 'org.suskalo/coffi)
|
||||||
(def version (format "0.1.%s-SNAPSHOT" (b/git-count-revs nil)))
|
(def version (format "0.1.%s-SNAPSHOT" (b/git-count-revs nil)))
|
||||||
|
|
||||||
(def source-dirs ["src/"])
|
(def source-dirs ["src/clj/"])
|
||||||
|
(def java-source-dirs ["src/java/"])
|
||||||
|
|
||||||
(def c-test-dirs ["test/c/"])
|
(def c-test-dirs ["test/c/"])
|
||||||
|
|
||||||
|
|
@ -42,6 +43,15 @@
|
||||||
[& path-components]
|
[& path-components]
|
||||||
(.exists ^java.io.File (apply io/file path-components)))
|
(.exists ^java.io.File (apply io/file path-components)))
|
||||||
|
|
||||||
|
(defn compile-java
|
||||||
|
"Compiles java classes required for interop."
|
||||||
|
[opts]
|
||||||
|
(.mkdirs (io/file class-dir))
|
||||||
|
(b/process {:command-args ["javac" "--add-modules=jdk.incubator.foreign"
|
||||||
|
"src/java/coffi/ffi/Loader.java"
|
||||||
|
"-d" class-dir]})
|
||||||
|
opts)
|
||||||
|
|
||||||
(defn- write-pom
|
(defn- write-pom
|
||||||
"Writes a pom file if one does not already exist."
|
"Writes a pom file if one does not already exist."
|
||||||
[opts]
|
[opts]
|
||||||
|
|
|
||||||
2
deps.edn
2
deps.edn
|
|
@ -1,4 +1,4 @@
|
||||||
{:paths ["src"]
|
{:paths ["src" "target/classes"]
|
||||||
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
|
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
|
||||||
insn/insn {:mvn/version "0.2.1"}}
|
insn/insn {:mvn/version "0.2.1"}}
|
||||||
:aliases
|
:aliases
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
(:import
|
(:import
|
||||||
(clojure.lang
|
(clojure.lang
|
||||||
IDeref IFn IMeta IObj IReference)
|
IDeref IFn IMeta IObj IReference)
|
||||||
|
(coffi.ffi Loader)
|
||||||
(java.lang.invoke
|
(java.lang.invoke
|
||||||
MethodHandle
|
MethodHandle
|
||||||
MethodHandles
|
MethodHandles
|
||||||
|
|
@ -567,19 +568,18 @@
|
||||||
(defn load-system-library
|
(defn load-system-library
|
||||||
"Loads the library named `libname` from the system's load path."
|
"Loads the library named `libname` from the system's load path."
|
||||||
[libname]
|
[libname]
|
||||||
(System/loadLibrary (name libname)))
|
(Loader/loadSystemLibrary (name libname)))
|
||||||
|
|
||||||
(defn load-library
|
(defn load-library
|
||||||
"Loads the library at `path`."
|
"Loads the library at `path`."
|
||||||
[path]
|
[path]
|
||||||
(System/load (.getAbsolutePath (io/file path))))
|
(Loader/loadLibrary (.getAbsolutePath (io/file path))))
|
||||||
|
|
||||||
(defn find-symbol
|
(defn find-symbol
|
||||||
"Gets the [[MemoryAddress]] of a symbol from the loaded libraries."
|
"Gets the [[MemoryAddress]] of a symbol from the loaded libraries."
|
||||||
[sym]
|
[sym]
|
||||||
(let [sym (name sym)]
|
(let [sym (name sym)]
|
||||||
(or (.. (CLinker/systemLookup) (lookup sym) (orElse nil))
|
(Loader/findSymbol sym)))
|
||||||
(.. (SymbolLookup/loaderLookup) (lookup sym) (orElse nil)))))
|
|
||||||
|
|
||||||
(defn- method-type
|
(defn- method-type
|
||||||
"Gets the [[MethodType]] for a set of `args` and `ret` types."
|
"Gets the [[MethodType]] for a set of `args` and `ret` types."
|
||||||
43
src/java/coffi/ffi/Loader.java
Normal file
43
src/java/coffi/ffi/Loader.java
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package coffi.ffi;
|
||||||
|
|
||||||
|
import jdk.incubator.foreign.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loading libraries with the {@link System#load} and {@link System#loadLibrary}
|
||||||
|
* relies on the classloader, which Clojure messes with. This class exists to
|
||||||
|
* have a consistent classloader, providing a consistent way to load libraries
|
||||||
|
* and symbols from them.
|
||||||
|
*/
|
||||||
|
public class Loader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a library from a given absolute file path.
|
||||||
|
*
|
||||||
|
* @param filepath The absolute file path of the library to load
|
||||||
|
*/
|
||||||
|
public static void loadLibrary(String filepath) {
|
||||||
|
System.load(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a library on the system loadpath with the given name.
|
||||||
|
*
|
||||||
|
* @param libname The library name, stripped of platform-specific prefixes and suffixes.
|
||||||
|
*/
|
||||||
|
public static void loadSystemLibrary(String libname) {
|
||||||
|
System.loadLibrary(libname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the memory address of a symbol.
|
||||||
|
*
|
||||||
|
* First attempts to load the symbol from system libraries, like libc, and
|
||||||
|
* afterwards attempts to load the symbol from other libraries.
|
||||||
|
*
|
||||||
|
* @param symbol The name of the symbol to load from a library.
|
||||||
|
*/
|
||||||
|
public static MemoryAddress findSymbol(String symbol) {
|
||||||
|
return CLinker.systemLookup().lookup(symbol)
|
||||||
|
.orElseGet(() -> SymbolLookup.loaderLookup().lookup(symbol).orElse(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue