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

欢迎!请查看 关于 页面以了解更多关于如何使用本网站的信息。

0
Java互操作

大家好,

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

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

根据以下示例 这里这里,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. 为了避免在每次加载Clojure包装器的C函数时重新加载库,我能编写一个类似的方法吗?

    (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

你的回复证实了我的感觉,那就是不编写用于将本机C代码库与Clojure接口的Java包装器是不可能的。

我在思考这个问题至少两周后发布了这个问题,所以我非常有信心能够从Java调用C函数,足以为我的Clojure项目编写包装器:)
+1

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

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

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

这两个库都可以通过使用JNA内部实现您想要的功能(不使用JNR-FFR)。

感谢Didier。有多种选择/替代方案总是好的 :)
...