I have seen a few posts on this, but I haven't seen any solutions so far. I have a .jar file that I'm converting to a .NET DLL via IKVM. I'm trying to figure out how to make the methods in the DLL available inside the excel VBA environment. here are the details.
1.) installed IKVM & registered it's DLL's to GAC
2.) ran IKVM to create the a .net .dll (mytest.dll)
ikvmc mytest.jar
3.) registered the new .dll
regasm mytest.dll
4.) From here i created a VB.NET project and added mytest.dll and IKVM.OpenJDK.Core.dll as references to the project. I am then able to access the methods within the .dll in .NET. This is great!
5.) what I really want to do is be able to use the .dll in VBA as well. Initially vba wouldn't accept the .dll directly as it's a .net library. I attempted to create a type library:
regasm /codebase /tlb mytest.dll
This created a .tlb file which is nice, but it did throw a warning about the library not being strongly named.
6.) then I loaded the .tlb as a reference in my vba editor. This works, however when I try to access the methods nothing shows up. Similarly if I look in the object viewer for my library i can see my two classes but not the members of those classes.
Additionally, I imagine that I probably also need to somehow reference the IKVM.OpenJDK.Core.dll inside VBA as well. However I can't do that either since it's a .NET .dll.
Has anyone had success converting a .jar file into something that can be used with VBA?
I think you always need to explicitly mark a class to be usable via COM interop. Here's an example of a Java class that is usable from VBA:
import cli.System.Runtime.InteropServices.*;
#ClassInterfaceAttribute.Annotation(ClassInterfaceType.__Enum.AutoDual)
public class SampleWidget {
public int Add(int x, int y) {
return x + y;
}
}
Here are the steps to compile:
Copy IKVM.Runtime.dll and all IKVM.OpenJDK.*.dll into the current directory or the GAC.
Run "ikvmstub mscorlib" to generate mscorlib.jar.
Create a Java source named SampleWidget.java containing the code above.
javac -cp mscorlib.jar;. SampleWidget.java
ikvmc -out:SampleLibrary.dll SampleWidget.class -r:mscorlib.dll
tlbexp SampleLibrary.dll
regasm /codebase SampleLibrary.dll (this step needs administrator rights)
Now you can add a reference to the SampleLibrary.tlb from VBA and use the SampleWidget class.
I have a dll file and I am trying to call functions of it through a Java program through JNA
But the problem is It is not able to locate my dll file and throwing the following exception:
java.lang.UnsatisfiedLinkError: Unable to load library 'UsbDll': The specified module could not be found.
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:163)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:236)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:199)
at com.sun.jna.Native.register(Native.java:1018)
at com.MainClass.<clinit>(MainClass.java:15)
Exception in thread "main"
Below is my program:
package com;
import com.sun.jna.Native
public class MainClass {
static {
Native.register("UsbDll");
}
public native int method();
public static void main(String[] args) {
}
}
The name of my dll file is UsbDll.dll and my operating system is Windows.
============================ EDITED ================================
The location of my dll file is "c:\UsbDll.dll"
When I placed another dll file at the same location, JNA has located it so I think that the problem is with my "UsbDll.dll" file only.
When I tried to load both the dll files (UsbDll.dll and the another dll) with the following command
System.load("c:\\UsbDll.dll");
System.load("c:\\another.dll");
It loaded the "another.dll" successfully but for "UsbDll.dll", it throws the following exception:
java.lang.UnsatisfiedLinkError: C:\UsbDll.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1699)
at java.lang.Runtime.load0(Runtime.java:770)
at java.lang.System.load(System.java:1003)
at com.MainClass.<clinit>(MainClass.java:16)
Exception in thread "main"
Q1. It looks like it is not finding some dependent libraries. But as I am totally new to these dlls, Is there anything I am missing or I need to ask the vendor to provide me the dependent libraries.
OR
Is it depends on some standard libraries which I can download from internet? If it is, then how to find the libraries name on which it depends?
============================ EDITED #2 ================================
I ran the Dependency Walker on my UsbDll.dll file to find the missing dependencies and found the following missing dependencies.
WER.DLL (referred by library WINNM.DLL found in my c:\windows\system32)
IESHIMS.DLL (referred by library WINNM.DLL found in my c:\windows\system32)
WDAPI920.DLL (referred directly by my UsbDll.dll)
Q1. As WINNM.DLL was found in my system32 folder, it seems as the standard dll. And if this standard dll is referring to 2 missing dlls (WER.DLL & IESHIMS.DLL), then I suspect how other applications are working who are using this WINNM.DLL file?
Q2. I googled for WDAPI920.dll (that was referred my UsbDll.dll directly) and many search results appeared with the same dll name. So it also looks like some standard library. So how to fix these dependencies? From where to download them? After downloading, Can I place them in the same directory in which my main dll (UsbDll.dll) is or I need to do something extra to load my dll (UsbDll.dll) sucessfully?
From your edited code it is quite evident that the UsbDll.dll depends on some standard modules which are not there on your system (for example if it uses ATL and if you have don't have proper runtime then it is guaranteed to fail). To resolve this you will need proper runtime environment.
Also it is possible that the dll in concern depends on some vendor specific module. For you the best option is (and fastest option would be) to contact the vendor. Otherwise, try to install proper runtime from the microsoft site (but its more of hit-and-trial)
Update
Use the below links for finding more about DLL dependency:
How do I determine the dependencies of a .NET application?
http://msdn.microsoft.com/en-us/library/ms235265.aspx
Command line tool to find Dll dependencies
Update 2
See the below mentioned link for the missing dll details (but it is specific to the windows version)
Dependency Walker reports IESHIMS.DLL and WER.DLL missing?
http://social.msdn.microsoft.com/Forums/en/vsx/thread/6bb7dcaf-6385-4d24-b2c3-ce7e3547e68b
From few simple google queries, WDAPIXXX.dll appears to be some win driver related thing (although i am not too sure). Check this link, they have something to say about WDAPI http://www.jungo.com/st/support/tech_docs/td131.html.
The DLL must by in the Path specified by LD_LIBRARY_PATH (see your env), or, in the case of JNA, in the current directory.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to bundle a native library and a JNI library inside a JAR?
I need to include native lib (jnotify but I think that it does't matter) to my jar. I want to do it with NetBeans.
I added Bundle-NativeCode: /lib/jnotify.dll; osname=win32 to my manifest.mf file and added jnotify.dll to projektHome\src\lib\ folder. But unfortunately NetBeans is overidning manifest.mf file.
How can I fixed? Can I do this using only NetBeans? Is it line 'Bundle-NativeCode: /lib/jnotify.dll; osname=win32 correct? I also heard I should put dlls hash in manifest.mf and sign my jar. Is that true?
I don't think the Java executable supports Bundle-NativeCode. I'm pretty sure that is an OSGi attribute. The list of supported attributes is defined in the JAR File Specification.
Outside frameworks that provide it, there is no built-in support for bundling native libraries inside JAR files. If I recall correctly, it is possible to extract the file to a temporary location and load it manually.
Sometimes i found the problem is not the Java way of loading native libs, but the 3rd party library that needs that native code.
The problem is that the 3rd party libs will do at some point (normally very early in initialization)
System.loadLibrary("native.dll");
And if native.dll is not at the appropiated place it throws an Error.
If you have access to the java source of the 3rd party library it might be easy to patch that code and you could easily extract your dll from the JAR and run System.load before using the 3rd party lib.
Update
I had a look into JNotify sources. It is exactly what i said:
public class JNotify_win32
{
static
{
System.loadLibrary("jnotify"); /* *** */
int res = nativeInit();
if (res != 0)
{
throw new RuntimeException("Error initialiing native library. (#" + res + ")");
}
}
Take line *** out or surround with try-catch, load with System.load() and you are done.
I ran into this problem when trying to hook a Windows shutdown event when the program runs on that OS. The solution I ended up using was essentially McDowell's - adding the DLL to the jar file and extracting it to a temporary location when the program starts. If it fits your program, you can leave the DLL in a more permanent place and then reference it on subsequent program startups. My application was used in an environment where the users might intentionally delete files they shouldn't, so I had to extract the DLL on every run. However, it hasn't resulted in any performance hit of significance.
How can I load a custom dll file in my web application? I've tried the following:
Copied all required dlls in system32 folder and tried to load one of them in Servlet constructor System.loadLibrary
Copied required dlls into tomcat_home/shared/lib and tomcat_home/common/lib
All these dlls are in WEB-INF/lib of the web-application
In order for System.loadLibrary() to work, the library (on Windows, a DLL) must be in a directory somewhere on your PATH or on a path listed in the java.library.path system property (so you can launch Java like java -Djava.library.path=/path/to/dir).
Additionally, for loadLibrary(), you specify the base name of the library, without the .dll at the end. So, for /path/to/something.dll, you would just use System.loadLibrary("something").
You also need to look at the exact UnsatisfiedLinkError that you are getting. If it says something like:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
then it can't find the foo library (foo.dll) in your PATH or java.library.path. If it says something like:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V
then something is wrong with the library itself in the sense that Java is not able to map a native Java function in your application to its actual native counterpart.
To start with, I would put some logging around your System.loadLibrary() call to see if that executes properly. If it throws an exception or is not in a code path that is actually executed, then you will always get the latter type of UnsatisfiedLinkError explained above.
As a sidenote, most people put their loadLibrary() calls into a static initializer block in the class with the native methods, to ensure that it is always executed exactly once:
class Foo {
static {
System.loadLibrary('foo');
}
public Foo() {
}
}
Changing 'java.library.path' variable at runtime is not enough because it is read only once by JVM. You have to reset it like:
System.setProperty("java.library.path", path);
//set sys_paths to null
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
Please, take a loot at: Changing Java Library Path at Runtime.
The original answer by Adam Batkin will lead you to a solution, but if you redeploy your webapp (without restarting your web container), you should run into the following error:
java.lang.UnsatisfiedLinkError: Native Library "foo" already loaded in another classloader
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646)
at java.lang.Runtime.load0(Runtime.java:787)
at java.lang.System.load(System.java:1022)
This happens because the ClassLoader that originally loaded your DLL still references this DLL. However, your webapp is now running with a new ClassLoader, and because the same JVM is running and a JVM won't allow 2 references to the same DLL, you can't reload it. Thus, your webapp can't access the existing DLL and can't load a new one. So.... you're stuck.
Tomcat's ClassLoader documentation outlines why your reloaded webapp runs in a new isolated ClassLoader and how you can work around this limitation (at a very high level).
The solution is to extend Adam Batkin's solution a little:
package awesome;
public class Foo {
static {
System.loadLibrary('foo');
}
// required to work with JDK 6 and JDK 7
public static void main(String[] args) {
}
}
Then placing a jar containing JUST this compiled class into the TOMCAT_HOME/lib folder.
Now, within your webapp, you just have to force Tomcat to reference this class, which can be done as simply as this:
Class.forName("awesome.Foo");
Now your DLL should be loaded in the common classloader, and can be referenced from your webapp even after being redeployed.
Make sense?
A working reference copy can be found on google code, static-dll-bootstrapper .
You can use System.load() to provide an absolute path which is what you want, rather than a file in the standard library folder for the respective OS.
If you want native applications that already exist, use System.loadLibrary(String filename). If you want to provide your own you're probably better with load().
You should also be able to use loadLibrary with the java.library.path set correctly. See ClassLoader.java for implementation source showing both paths being checked (OpenJDK)
In the case where the problem is that System.loadLibrary cannot find the DLL in question, one common misconception (reinforced by Java's error message) is that the system property java.library.path is the answer. If you set the system property java.library.path to the directory where your DLL is located, then System.loadLibrary will indeed find your DLL. However, if your DLL in turn depends on other DLLs, as is often the case, then java.library.path cannot help, because the loading of the dependent DLLs is managed entirely by the operating system, which knows nothing of java.library.path. Thus, it is almost always better to bypass java.library.path and simply add your DLL's directory to LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS), or Path (Windows) prior to starting the JVM.
(Note: I am using the term "DLL" in the generic sense of DLL or shared library.)
If you need to load a file that's relative to some directory where you already are (like in the current directory), here's an easy solution:
File f;
if (System.getProperty("sun.arch.data.model").equals("32")) {
// 32-bit JVM
f = new File("mylibfile32.so");
} else {
// 64-bit JVM
f = new File("mylibfile64.so");
}
System.load(f.getAbsolutePath());
For those who are looking for java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path
I was facing same exception; I tried everything and important things to make it work are:
Correct version of pdf lib.jar ( In my case it was wrong version jar kept in server runtime )
Make a folder and keep the pdflib jar in it and add the folder in your PATH variable
It worked with tomcat 6.
If you believe that you added a path of native lib to %PATH%, try testing with:
System.out.println(System.getProperty("java.library.path"))
It should show you actually if your dll is on %PATH%
Restart the IDE Idea, which appeared to work for me after I setup the env variable by adding it to the %PATH%
The issue for me was naming:
The library name should begin with "lib..." such as libnative.dll.
So you might think you need to load "libnative": System.loadLibrary("libnative")
But you actually need to load "native": System.loadLibrary("native")
Poor me ! spent a whole day behind this.Writing it down here if any body replicates this issue.
I was trying to load as Adam suggested but then got caught with AMD64 vs IA 32 exception.If in any case after working as per Adam's(no doubt the best pick) walkthrough,try to have a 64 bit version of latest jre.Make sure your JRE AND JDK are 64 bit and you have correctly added it to your classpath.
My working example goes here:unstatisfied link error
I'm using Mac OS X Yosemite and Netbeans 8.02, I got the same error and the simple solution I have found is like above, this is useful when you need to include native library in the project. So do the next for Netbeans:
1.- Right click on the Project
2.- Properties
3.- Click on RUN
4.- VM Options: java -Djava.library.path="your_path"
5.- for example in my case: java -Djava.library.path=</Users/Lexynux/NetBeansProjects/NAO/libs>
6.- Ok
I hope it could be useful for someone.
The link where I found the solution is here:
java.library.path – What is it and how to use
It is simple just write java -XshowSettings:properties on your command line in windows and then paste all the files in the path shown by the java.library.path.
I had the same problem and the error was due to a rename of the dll.
It could happen that the library name is also written somewhere inside the dll.
When I put back its original name I was able to load using System.loadLibrary
First, you'll want to ensure the directory to your native library is on the java.library.path. See how to do that here. Then, you can call System.loadLibrary(nativeLibraryNameWithoutExtension) - making sure to not include the file extension in the name of your library.
My first attempt at jython is a java/jython project I'm writing in eclipse with pydev.
I created a java project and then made it a pydev project by the RightClick project >> pydev >> set as... you get the idea. I then added two source folders, one for java and one for jython, and each source folder has a package. And I set each folder as a buildpath for the project. I guess I'm letting you know all this so hopefully you can tell me wether or not I set the project up correctly.
But the real question is: how do I get my jython code made into a class file so the java code can use it? The preferred method would be that eclipse/pydev would do this for me automatically, but I can't figure it out. Something mentioned in the jython users guide implies that it's possible but I can't find info on it anywhere.
EDIT: I did find some information here and here, but things are not going too smooth.
I've been following the guide in the second link pretty closely but I can't figure out how to get jythonc to make a constructor for my python class.
Jythonc doesn't exist anymore, it has been forked off to another project called Clamp, but with that said...
...you can pre-compile
your python scripts to .class files
using:
jython [jython home]/Lib/compileall.py
[the directory where you keep your
python code]
Source - Jython Newsletter, March 2009
When I fed it a folder with Python 2.7 code (knowing it would fail in Jython 2.5) it did output a .class file, even though it doesn't function. Try that with your Jython scripts. If it works, please let us know, because I'll be where you are soon enough.
Once you're that far, it isn't hard to convert your command line statement to an External Tool in PyDev that can be called as needed.
Following the "Accessing Jython from Java Without Using jythonc" tutorial it became possible to use the jython modules inside java code. The only tricky point is that the *.py modules do not get compiled to *.class files. So it turns out to be exotic scripting inside java. The performance may of course degrade vs jythonc'ed py modules, but as I got from the jython community pages they are not going to support jythonc (and in fact have already dropped it in jython2.5.1).
So if you decide to follow non-jythonc approach, the above tutorial is perfect. I had to modify the JythonFactory.java code a bit:
String objectDef = "=" + javaClassName + "(your_constructor_params here)";
try {
Class JavaInterface = Class.forName(interfaceName);
System.out.println("JavaInterface=" + JavaInterface);
javaInt =
interpreter.get("instance name of a jython class from jython main function").__tojava__(JavaInterface);
} catch (ClassNotFoundException ex) {
ex.printStackTrace(); // Add logging here
}