Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending (not implementing) Java interfaces in Clojure

Tags:

clojure

jna

I've been looking a lot at Clojure recently and I've been wondering if it suits the scope of my next project. Unfortunately, it involves writing non-portable code and I need access to the Win32 API.

I stumbled upon the Java Native Access library for easily mapping native libraries with a C interface into Java. It even provides an (empty) wrapper for Kernel32.dll as an example in the tutorial!

However, I'm a bit stumped as to translating the examples from Java to Clojure. I know I can implement interfaces and implement classes, but how can I simply extend an interface?


Thanks to the link posted by Joost, here is a minimal working example:

(import (com.sun.jna Library Native Platform Pointer))
(import (com.sun.jna.win32 StdCallLibrary))

(def K32
     (gen-interface
      :name Kernel32
      :extends [com.sun.jna.win32.StdCallLibrary]
      :methods [[GetCurrentProcess [] com.sun.jna.Pointer]]))

(defn load-native-library [name interface]
  (cast interface (com.sun.jna.Native/loadLibrary name interface)))

(def k32 (load-native-library "kernel32" K32))

(println (.GetCurrentProcess k32))

Outputs #<Pointer native@0xffffffff>, as expected!

like image 753
André Caron Avatar asked Mar 29 '11 22:03

André Caron


1 Answers

You can only extend an interface with another interface. I'm at a loss why you'd need that functionality when accessing an existing API - even in Java. Just implement it and be done with it.

EDIT: and usually, in my experience, it's much clearer to write your interfaces in pure Java; the usual reason for defining a new Interface in clojure is when you want to add a Java-friendly interface to some clojure code anyway.

EDIT AGAIN: You can use definterface if you find that more attractive for this case. This blog post has a few examples using it for accessing JNA.

like image 57
Joost Diepenmaat Avatar answered Oct 11 '22 19:10

Joost Diepenmaat