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"]
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
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