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

欢迎!请参阅关于页面以了解更多关于如何使用此信息。

0
Java Interop

大家好,

我想在不写Java代码的情况下,从Clojure中调用C库中的本地函数。

(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
by
已选择 by
 
最佳答案

1. Clojure 不支持所有的Java类关键字。创建一个Java类,构建一个.class文件,然后从Clojure中使用它。

2. 从Clojure中,你可以访问任意Java方法。只需检查你库的javadoc,或者使用clojure.reflect/reflect来了解您对象的全部方法。

3. 是(?!)

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

建议您先学习“如何在Java中调用C函数”,一旦掌握,再尝试将Java项目迁移到Clojure。

by
谢谢Enzzo

您的回复证实了我的感觉,那就是不编写Java包装器来使Clojure与本地C代码库交互是不可能的。

我在思考至少两周这个问题后发布了这个问题,所以我相当自信我可以从Java调用足够的C函数来为我的Clojure项目编写包装器 :)
+1
by

您明确要求JNR-FFI解决方案,但有其他Clojure库不基于JNR-FFI,可以实现相同功能。请查看以下内容:

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

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

两者都使用JNA(不是JNR-FFI)来实现您想要的功能。

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