Clojure/QuantLib interop: classloading woes

396 views Asked by At

Problem Statement:

I wish to call a QuantLib Java function from a Clojure namespace, as follows:

(Date. 21 Month/September 2013)

So far, I have done the following:

$ brew install boost
$ brew install quantlib

Downloaded the generated SWIG interfaces.

Created a new Leiningen project.

Copied said interfaces into src/main/java/org/quantlib/

Added:

:jvm-opts ["-Djava.library.path=src/main/java"]
:java-source-paths ["src/main/java/"]

to my project.clj.

I have followed Bojan Nikolic's instructions on solving a very similar classloading problem, adding a class BKLoader.

When I load my core.clj file into the REPL, I get the following error:

UnsatisfiedLinkError org.quantlib.QuantLibJNI.new_Date__SWIG_1(III)J org.quantlib.QuantLibJNI.new_Date__SWIG1 (QuantLibJNI.java:-2)

Bojan Nikolic has a recommendation to handle these classloading problems that I implemented as well in trying to run this down. Per that link, I added a new static class BKLoader to load QuantLibJNI, loaded it with the other Java classes and tried loading core.clj into the REPL again, to the resounding trumpets of:

UnsatisfiedLinkError no QuantLibJNI in java.library.path java.lang.Classloader.loadLibrary (ClassLoader.java:1758)

At which point I rip out B. Nikolic's class from the ns declaration in my core.clj and take a look at classlojure.

Per Apage43's suggestion in #clojure, at this point I drop the following into my core.clj:

(classlojure/with-classloader
  (.getClassLoader Date) 
  (System/loadLibrary "QuantLibJNI"))

Which results in the same error as when calling the BKLoader class.

I appreciate any insight any of y'all can bring to bear. Thanks!

Solution

The solution is to add the QuantLib jar to :java-source-paths in project.clj:

:java-source-paths ["src/main/java" "/usr/local/lib/QuantLib.jar"]
1

There are 1 answers

2
GerritCap On BEST ANSWER

The error indicates that the java vm cannot find a DLL it needs.

so probably the dll it wants to load is not available in src/main/java from the directory where you launch the file as you specified it to find it via

:jvm-opts ["-Djava.library.path=src/main/java"]

Sometimes it is the dll that is not in there, but sometimes a dll also wants to load other dll's so it might be a good idea in that case to also set your environment variable PATH to point to the directories where other dll's can be loaded.

There is a tool from microsoft where you can trace the dll's being loaded or needed, one is the dependencyWalker and another is the processmonitor. Both free to download from somewhere in www.microsoft.com