I have a library which is written in C++ (actually a Firefox plugin, xyz.dll) and I need to access its methods from Java.
public class AccessLibrary {
public interface Kernel32 extends Library {
public void showVersion();
}
public static void main(String[] args) {
Kernel32 lib = (Kernel32) Native.loadLibrary("xyz.dll", Kernel32.class);
lib.showVersion();
}
}
While executing got the following error:
java -jar dist/accessLibrary.jar
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'showVersion': The specified procedure could not be found.
In the native library source code, the method is defined like this
void CPlugin::showVersion() {
/* ... */
}
I am very new to Java. May be I am missing something basic. Looked into similar questions but none of them solves my problem.
Forgot to mention I am using Windows 7 64bit and Java 7.
First, you cannot export a class method and load it into java. The name will get mangled, and java wouldn't know how to call it properly. What you need to do is break it out into a separate function on its own.
After that:
As already pointed out, make sure you export the function. You can export using one of two ways. The first is what is mentioned, which is to use __declspec( dllexport ). The second is to put it into the def file.
Additionally, make sure you mark it as extern "C" otherwise the name will get mangled. All the details are here: Exporting functions from a DLL with dllexport
So the the signature should be something like this:
extern "C" __declspec(dllexport) void showVersion () {
}
Finally, the depends tool can be downloaded here: http://www.dependencywalker.com/
I think your native library needs to provide a C-style interface, for example
__declspec( dllexport ) void showVersion() {
/* ... */
}
Ideally, take a look at your DLL with depends.exe (which is available through the Windows SDK), there you'll see if your DLL provides the correct function exports.
Related
I am having a .dll file which has a wrapper in C,C++, .Net and python, but not in Java. I am successful in loading the .dll file using following code in my Java
public class
public static void main(String[] {
// print when the program starts
System.out.println("Program starting...");
System.out.println("Loading Library...");
Runtime.getRuntime().loadLibrary("HelloJava");
System.out.println("Library Loaded.");
}
}
which gives the following output:
Now my question is that if this file is loaded, How do I access it's functions to use in my Java workspace?
Since it is the C-DLL, so How should I fetch the module values from this .dll.
Note:
I have made a folder named dll under my Java project path from where I loaded the library in the above code.
I browsed for the concept for JNA and JNI but lacked the understanding concept, that's why posted the question.
Thanks in advance.
I think you need to know the methods in your DLL first. I really don't know how to list the methods using JNA or JNI, but you have to know the method's signature before starting, maybe from a documentation, because you normally can find the DLL's documentation on the web, or you even can use a Reflector (like red-gate) to find out your methods.
Then:
Download the JNA .jar file and add it to your build in your Java project.
Put the .dll in the root directory of your Java project.
Create an Interface that contains the functions from the dll that you want to use.
For example, lets say your HelloWorld DLL has a String hello(String hey) method in C++, then in your Java project you will have to do something like:
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Main {
public interface Ihello extends Library {
public String hello(String hey);
}
public static void main(String args[]) {
//"hello-world is the name my DLL, for example.
Hello h = Native.load("hello-world", Hello.class);
System.out.println(h.hello(" John! ");
}
}
Here is a good example, regards.
I've got a dll written in Pascal. I've determined that I need to run CoInitialize in the Java code, but I just can't figure out how.
I found another Stack Overflow thread which should have helped here: https://stackoverflow.com/questions/15763993 but I couldn't understand how it actually worked.
My current code that I have now is here:
public interface CSQLLib extends StdCallLibrary {
CSQLLib INSTANCE = (CSQLLib) Native.loadLibrary("DatabaseLibrary", CSQLLib.class);
public HRESULT CoInitialize(Pointer p);
public HRESULT CoUninitialize();
public String doSQLQuery(String input);
public void DllMessage();
}
Example of calling CoInitializeEx from Java code using JNA:
import com.sun.jna.platform.win32.Ole32;
public class Example {
public static void main(String[] args) {
Ole32.INSTANCE.CoInitializeEx(null,Ole32.COINIT_APARTMENTTHREADED);
}
}
Note that use of CoInitializeEx is recommended by both the JNA docs and the Windows SDK docs instead of CoInitialize. CoInitialize(null) is equivalent to CoInitializeEx(null,Ole32.COINIT_APARTMENTTHREADED), but the JNA docs recommend using COINIT_MULTITHREADED instead in Java apps (indeed, they call it "the only sane choice") – however, despite what they say, some COM interfaces only work correctly with COINIT_APARTMENTTHREADED, so it really depends on the COM objects you are using. Whichever you choose, CoInitializeEx is better because it makes it obvious (rather than implicit) which COM threading mode you are using.
Note the solution you mentioned in your comment, calling CoInitialize from within your DLL written in Delphi, is not a good practice. COM should be initialised in the application not in a DLL. If you ever attempt to reuse your DLL in some other application (which is already calling CoInitialize/CoInitializeEx), it is likely your call to it will fail with S_FALSE or RPC_E_CHANGED_MODE because the application will have already initialised it.
I have a native DLL abc.dll (without source code) that was originally used in a JNI call in Java like this:
public class ABC_Proxy
{
private native void callABC(String parameter);
public ABC_Proxy()
{
System.loadLibrary("abc");
}
public void Start(String paramater)
{
callABC(paramater);
}
}
Now I am trying to execute the same function in C#. Using dumpbin I found the correct full entry point, and this is what I came up with so far:
class Abc
{
[DllImport("abc.dll", EntryPoint="_Java_my_namespace_abc_1Proxy_callABC#12")]
private static extern void CallAbc(string parameter);
public void Start(string parameter)
{
CallAbc("test");
}
}
I can see that CallAbc is executed and does something (it creates a file) but then it throws an AccessViolationException, presumably when it tries to access the parameter.
The PureDLLHelper suggests that the function has 3 parameters, and after reading this JNI tutorial I have the feeling that I also need to pass the parameters JNIEnv*, jobject to simulate a JNI call. But from here on I'm lost...
Any idea? Is it even possible what I'm trying to achieve?
Edit: I just want to mention this forum post that has a good explanation of the problems involved and how they could by solved. However, the solutions are based on Xamarin.Android to bridge the C#/Java gap and get hold of the JNIEnv, which is not really an option for me.
Its not going to work, simple as that. The JNI DLL is designed and built to be loaded by the JVM. You will not be able to provide the pointers to the env or jvm that are required to call any of the functions contained in that library. Your only option would be to create a second DLL that creates a new instance of the JVM that then calls the DLL you have, but if you are calling Java from .Net, you may as well keep it all in Java.
I am new in Java, searched for this question in google and stackoverflow, found some posts, but still I can't understand.
I want to use DLL libary (C++) methods from Java. I use JNA for this purpose. JNA found my library but it can't find my method:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'LoadCurrentData': The specified procedure could not be found.
My code:
package javaapplication1;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class JavaApplication1 {
public interface LibPro extends Library {
LibPro INSTANCE = (LibPro) Native.loadLibrary(
(Platform.isWindows() ? "LibPro" : "LibProLinuxPort"), LibPro.class);
public short LoadCurrentData();
}
public static void main(String[] args) {
LibPro sdll = LibPro.INSTANCE;
sdll.LoadCurrentData(); // call of void function
}
}
I looked in my DLL with Depency Walker Tool and saw that my function name has prefix and suffix - it looks like _LoadCurrentData#0
Thanks for response!
P.S. I found good example which works http://tutortutor.ca/cgi-bin/makepage.cgi?/articles/rjna (Listing 6).
I'd say that you need to apply correct name mapper, as you noticed function name got mangled, you need to register CallMapper that will implement the same mangling as your compiler.
Here is a revelant entry from JNA homepage:
Use a dump utility to examine the names of your exported functions to make sure they match (nm on linux, depends on Windows). On Windows, if the functions have a suffix of the form "#NN", you need to pass a StdCallFunctionMapper as an option when initializing your library interface. In general, you can use a function mapper (FunctionMapper) to change the name of the looked-up method, or an invocation mapper (InvocationMapper) for more extensive control over the method invocation.
Here is a possibly revelant question: renaming DLL functions in JNA using StdCallFunctionMapper
I am trying to open a URL with the default Windows browser, in Java. Unfortunately, I cannot use the Desktop class utilities since the code has to be compatible with 1.5.
As a solution, I am calling ShellExecute by using a native method:
public class ShellExec {
public native int execute(String document);
{
System.loadLibrary("HSWShellExec");
}
public static void main(String args[]) throws IOException {
new ShellExec().execute("http://www.google.com/");
}
}
I put the DLL file in the Eclipse project root which apparently is included in java.library.path .
Everything works just perfect if ShellExec is in the default package, but if I move it in any other package, the native call fails with:
Exception in thread "main" java.lang.UnsatisfiedLinkError: apackage.ShellExec.execute(Ljava/lang/String;)I
at apackage.ShellExec.execute(Native Method)
at apackage.ShellExec.main(ShellExec.java:13)
Anybody has any ideea why? I am using the DLL from http://www.heimetli.ch/shellexec.html
Thanks
..later edit:
Eventually this class, and others, will be utility classes in an Eclipse RCP application, and all the external DLLs will be placed in a common lib folder to which the java.library.path will point to. The DLLs are seen, but I get the same type of errors as the simple example from above.
pass the VM argument -Djava.library.path=<path-to-dll-folder> to your project launch configuration.
The block you are loading the library in is not static to the class, just defined as an anonymous block in an instance of ShellExec. Since you never create an instance of ShellExec, the anonymous block never gets called and the library never gets loaded.
Instead you should have
static {
System.loadLibrary("HSWShellExec");
}
I think that will solve your problem.