请分享您的想法参加2024年Clojure状态调查!

欢迎!请查看关于页面了解有关此功能的更多信息。

0 投票
Java 互操作

大家好,

我想通过JNR-FFI从Clojure调用C库中的原生函数,而不必编写Java代码。

(defproject mypkg
	:dependencies [[org.clojure/clojure "1.10.1"]
				   [com.github.jnr/jnr-ffi "2.2.0"]])

基于这里这里的jnr-ffi示例,Java包装器可能看起来像这样

package blahblah;

public class BlahNative {
	private static int[] intDummy;
	private static double[] doubleDummy;

	public BlahNative() {
	}

	public static native void native_a(char var0, char var1, int var2, int var3, int var4, double[] var7, int var8, int var9);

	public static native void native_b(char var0, char var1, int var2, int var3, int var4, double[] var7, int var8, int var9);

	static {
		lib = LibraryLoader
            .create(LibSodium.class)
            .search("/usr/local/lib")
            .search("/opt/local/lib")
            .search("/usr/lib")
            .search("/lib")
            .load(LIBRARY_NAME);
        initializeLibrary(lib);
    }
}

我假设我的Clojure命名空间应该使用gen-class特性来实现Java类。

(ns mypkg.native
	(:import [jnr.ffi LibraryLoader])
	(:import [jnr.ffi.annotations IgnoreError])
	(:import [jnr.ffi.provider FFIProvider])
    (:gen-class))

那么,

  1. 如何在Clojure中编写原生方法?换句话说,在使用Clojure的Java互操作特性时,我是否需要指定方法类型(如native)?

  2. 加载了本地库之后,我不知道如何访问库中的C函数。我该如何 doing

  3. 为了避免每次加载库时都重新加载库以调用每个C函数的Clojure包装器函数,我可以编写以下方法

    (defn lib (. LibraryLoader load LIBRARY_NAME))

然后访问其中的本地函数?

我既不是C专家也不是Java专家,所以任何指导都非常欢迎。

谢谢。

2 个回答

+1

选定
 
最佳回答

1. Clojure 不能支持所有/每个 Java 类的关键字。创建一个 Java 类,编译成 .class 文件,并在 Clojure 中使用它。

2. 从 Clojure 可以访问 Java 中的任何方法。只需检查您库的 javadocs,或使用 clojure.reflect/reflect 来了解您的对象的所有方法。

3. 是的(!?)

  • 我既不是C专家也不是Java专家,所以任何指导都非常欢迎。

我建议您先回顾一下 "如何从 Java 调用 C 函数",一旦您掌握它,再尝试将代码从 Java 转移到 Clojure 中。

感谢 Enzzo

您的回答证实了我的感觉:如果不编写 Java 包装器来将原生 C 代码库与 Clojure 接口,就无法解决这个问题。

我在思考了至少两周这个问题之后发布了这个问题,所以我觉得我可以足够好地从 Java 调用 C 函数,以至于我可以为我的 Clojure 项目编写包装器:)
+1

您明确要求一个 JNR-FFI 解决方案,但也有一些不基于 JNR-FFI 的替代 Clojure 库可以实现您想要的功能。请查看

https://github.com/Chouser/clojure-jna

或者

https://github.com/techascent/tech.jna

两者都可以通过在底层使用 JNA(而不是 JNR-FFI)来实现您的需求。

谢谢Didier。有选项/替代方案总是好的 :)
...