Welcome! Please see the About page for a little more info on how this works.

0 votes
in Java Interop by

Hi Everyone,

I want to call native functions in a C-Library from Clojure via JNR-FFI without having to write Java code.

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

Based on the jnr-ffi examples here and here a Java wrapper might look like

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);
    }
}

I presume my Clojure namespace should use the gen-class feature for implementing Java classes.

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

Then,

  1. How do I write a native method in Clojure? In other words, do I even need to specify the method type (as native) when using Clojure's Java interop features?

  2. After loading the native library I do not know how to access the C-functions in the library. How do I do it?

  3. To avoid reloading the library for every Clojure wrapper function of each C-functions, can I write a method like

    (defn lib (. LibraryLoader load LIBRARY_NAME))

and then access the native functions in it?

I am neither a C nor a Java expert so any guidance will be much appreciated.

Thanks.

2 Answers

+1 vote
by
selected by
 
Best answer

1. Clojure do not support all/every java class keyword. Create a java class, build a .class file and use it from clojure.

2. from clojure you can access any methods from java. Just check the javadocs of your library, or use clojure.reflect/reflect to know all methods from your object.

3. yes (?!)

  • I am neither a C nor a Java expert so any guidance will be much appreciated.

I recommend you to step back and first learn "how to invoke C functions from java", once you get it right, you try to port your code from java to clojure

by
Thanks Enzzo

Your response just confirmed my feeling that there is no going about not writing a Java wrapper to interface the native C-code library with Clojure.

I posted the question after at least two week of constantly thinking about this problem so I feel fairly confident that I can invoke C functions from Java enough to write my wrapper for my Clojure project :)
+1 vote
by

You explicitly asked for a JNR-FFI solution, but there are alternative Clojure libraries not based on JNR-FFI that allow you to do what you want. Have a look at:

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

or

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

Both can do what you want by using JNA under the hood (not using JNR-FFR).

by
Thanks Didier. Its always good to have options/alternative :)
...