请在2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以获取更多关于其工作方式的信息。

0
in Java 互操作 by

大家好,

我想在Clojure中通过JNR-FFI调用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函数。我该如何做?

  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. yes (?!)

  • 我不是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-FFR。

by
谢谢迪迪尔。有更多选择总是好的 :)
...