Use dll with java

Loading DLL in Java — Eclipse — JNI

I am trying to load a dll in java using the following code System.loadLibrary(«mydll»); The project is placed in D:\development\project\ and i have placed the dll on D:. I then gave following VM argument in eclipse configuration -Djava.library.path=D:/ But when i run i get UnsatisifiedLinkerError. After googling a bit, I used System.load(«D:\mydll.dll»); but again getting the same problem, could someone can help?

I tested my classpath with this code System.getProperty(«java.class.path») and placed the dll on that specific path. After that, I am getting error «Can’t find dependent libraries». How can i check which libraries it is asking :S. I am using some thirdparty Dll.

9 Answers 9

Where you specify the DLL filename in the library path, omit that. Additionally, your System.loadLibrary call should just be ‘mydll’. I can tell you (from experience) that if you put the DLL in the root of your project in Eclipse (i.e., D:\Eclipse Workspace\Proj), it should work. Any further linker errors could be from dependency problems with finding other DLLs. The exception is the same. Use something like Dependency Walker (http://www.dependencywalker.com/) to see if your DLL relies on anything else not on the system library path.

Edit: UnsatisfiedLinkError: Thrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native — it seems like you are using a JNI function which does not exist.

Читайте также:  Язык разметки гипертекста html практические работы

One problem you have is: System.load(«D:\mydll.dll»); should be System.load(«D:\\mydll.dll»); or System.load(«D:/mydll.dll»);

I have had more success with System.load, but loadlibrary is better designed for multiplatform. It figures out the extension for you.

Check out how to properly set up the native dependencies here. Additionally, make sure you use the correct JVM: in my case, the DLL was not found because it was a 32 bit DLL, but I used the x64 JVM!

Using System.loadLibrary(«mydll») works fine, you can also use that one. If you used javah and you think with your DLL everything is fine, there are two possibilies:

  1. The JVM does not find your DLL: In this case, your java library path is not correct (which I doubt) and you should probably set it to . and place your DLL in the current working dir.
  2. The JVM does not find a DLL your DLL depends on: If you have any dependent libraries in your DLL, they are NOT searched by the JVM, but by Windows itself. And Windows does not know the java.library.path , so it will look in the system PATH variable for those. If you have the possibility, you can set the system PATH variable to the location of your DLLs before starting the JVM and everything will be fine. Or you can load all your DLLs using the JVM like this

Источник

C# to Java (вызов C# dll из Java)

Доброго времени суток!
Помучив немного хабра поиск не нашел подобных тем, в связи с чем создал свою.

Немного лирики:
Имеем шарповскую библиотеку, в которой лежат необходимые для работы методы. Необходимо этими методами воспользоваться из Java программы.

Пример первый

Сначала покажу простой пример.
Имеем примитивную dll на шарпе, назовем ее SharpClass:

public class CSharpHelloWorld < public CSharpHelloWorld() < >public void displayHelloWorld() < Console.WriteLine("Hello World From C#!"); >> 

Будем собирать этот класс в сборку:
Открываем командную строку, и прописываем такую команду (предварительно нужно зайти в директорию с нашим SharpClass.cs файлом): csc \t: module SharpClass.cs. Если команда не работает, то перед ее запуском нужно выполнить бат-файл, у меня он находится здесь — C:\Program Files\Microsoft Visual Studio 9\VC\bin\vcvars32.bat
После выполнения сей процедуры мы получим файл SharpClass.netmodule, находящийся в одной папке с исходником.

Для связи между .NET и JVM нужен враппер (обертка для получения unmanaged кода). Создадим обертку из с++ с использованием явовской библиотеки jni.h и майкрософтовской библиотеки mscorlib.dll
Создаем с++ обертку:

#using #using "SharpClass.netmodule" using namespace System; __gc class HelloWorldC < public: CSharpHelloWorld __gc *t; HelloWorldC() < t = new CSharpHelloWorld(); >void method() < t ->displayHelloWorld(); > >; 

После написания этого кода необходимо указать ссылку на mscorlib.dll. Для этого заходим в настройки проекта и сначала находим General, где в пункте Common Language Runtime Support выбираем Common Language Runtime Support, Old Syntax (/clr:oldSyntax), после этого жмем References (ссылки) и добавляем новую — во вкладке .NET будет искомая dll (так было в VS2005).

#include "C:\Program Files\Java\jdk1.6.0_02\include\jni.h" #include "HelloWorld.h" #include "1.cpp" JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject) < HelloWorldC* t = new HelloWorldC(); t->method(); > 
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject); 

И последний хедер генерируется при помощи Java из командной строки запуском команды — javah -jni «имя класса без кавычек и без .class» (создавать его естественно нужно после компиляции ява программы, иначе сам класс просто не появится). В файлах 1.h и 2.cpp код также взят из последнего хедера.

#ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" < #endif /* * Class: HelloWorld * Method: displayHelloWorld * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject); #ifdef __cplusplus >#endif #endif 

После этого весь c++ проект строится в dll. Назовем его HelloWorld.dll.

Теперь переходим к Яве. Вот простой код для вызова нашей HelloWorld.dll:

import java.io.*; class HelloWorld < public native void displayHelloWorld(); static < System.load("C:\\Java_C#\\JavaApplication1\\HelloWorld.dll"); >public static void main(String[] args) < new HelloWorld().displayHelloWorld(); >> 

Вот собственно все готово. Ну и наш SharpClass.netmodule также необходимо перенести в папку с загружаемой сишной dll.

Пример второй

В первом примере рассматривался простой случай просто с выводом текста на экран. Сейчас рассмотрим случай, когда функция на C# принимает параметры и возвращает значение.
C# класс:

using System; using System.Collections.Generic; using System.Text; public class CSharpToJava < public CSharpToJava() < >public String returnValue(String value) < string ss = " cvb"; String answer = value+ss; return answer; >> 

Java приложение, использующее этот класс:

public class Main < public native String returnValue(String value); static < System.load("C:\\Java\\SharpToJava\\CSharpToJava.dll"); >public static void main(String[] args) < String value="Privet"; String val = new Main().returnValue(value); System.out.println(val); >> 

После этого создаем хедер для с++ с помощью команды, описанной в первом примере.
Далее создаем с++ обертку, которая таскает переменные из одного конца в другой :). Будет 3 файла — wrapper.cpp, CSharpToJava.cpp, Main.h (последний получается выполнением команды javah -jni над явовским классом)

#include #include #using //Подключение майкрософтовской библиотеки для создания native кода #using "CSharpClass.netmodule" //Подключение шарповской сборки, в который содержится вызываемая из явы функция using namespace std; using namespace System; //Создаем класс-обертку для преобразования шарповской функции в native код __gc class SendValue < public: CSharpToJava __gc *t; //CSharpToJava - класс шарпа. //t - указатель на него из с++ SendValue() < t = new CSharpToJava(); >String __gc* method(String __gc* value) < return (t ->returnValue(value)); > >; 
#include "C:\Program Files\Java\jdk1.6.0_02\include\jni.h" #include "Main.h" #include "wrapper.cpp" #include #include using namespace System::Runtime::InteropServices; //нужен для использования Marshal class, который делает перевод из String* в const Char* using namespace std; //Main функция //Экспортируемая функция из явы //Заголовок получается путем выполнения команды javah -jni "имя класса, пишется без кавычек и .class" JNIEXPORT jstring JNICALL Java_Main_returnValue (JNIEnv* env, jobject, jstring jvalue) < //Получение переменной jvalue, передаваемой из явы и присвоение сишной переменной value с типом String __gc* String __gc* value=env->GetStringUTFChars(jvalue,0); //Получение указателя на объект класса SendValue, который описан в wrapper.cpp SendValue* t = new SendValue(); //Получение значения из шарповской функции и присвоение его переменной val типа String __gc* String __gc* val = t->method(value); //Преобразование типа String* в const char* char* str2 = (char*)(void*)Marshal::StringToHGlobalAnsi(val); jstring jval; //Преобразование типа const char* в jstring, который требует вернуть функция явы jval=env->NewStringUTF(str2); //Возвращение явовской переменной return jval; > 
/* DO NOT EDIT THIS FILE - it is machine generated */ /* Header for class Main */ #ifndef _Included_Main #define _Included_Main #ifdef __cplusplus extern "C" < #endif /* * Class: Main * Method: returnValue * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_Main_returnValue (JNIEnv *, jobject, jstring); #ifdef __cplusplus >#endif #endif 

Заключение

Ну вот собственно и все. Данный код писал и испытывал 2 года назад, а сюда все никак руки не доходили написать. Когда разбирался с этой задачей, пытался просить помощи на одном форуме. Пока помощи просил, сам немного разобрался и написал свое решение.

Полезные ссылки

Источник

How to call a method in DLL in a Java program

This dll contaings a method that I need to access. How can I execute the method present in DLL in my Java file. Do I create an object or something of the DLL and then get the method name after the dot operator.

2 Answers 2

package jnahelloworldtest; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.Platform; import com.sun.jna.*; /** Simple example of native library declaration and usage. */ public class Main < public interface simpleDLL extends Library < simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary( (Platform.isWindows() ? "simpleDLL" : "simpleDLLLinuxPort"), simpleDLL.class); // it's possible to check the platform on which program runs, for example purposes we assume that there's a linux port of the library (it's not attached to the downloadable project) byte giveVoidPtrGetChar(Pointer param); // char giveVoidPtrGetChar(void* param); int giveVoidPtrGetInt(Pointer param); //int giveVoidPtrGetInt(void* param); int giveIntGetInt(int a); // int giveIntGetInt(int a); void simpleCall(); // void simpleCall(); >public static void main(String[] args) < simpleDLL sdll = simpleDLL.INSTANCE; sdll.simpleCall(); // call of void function int a = 3; int result1 = sdll.giveIntGetInt(a); // calling function with int parameter&result System.out.println("giveIntGetInt("+a+"): " + result1); String testStr = "ToBeOrNotToBe"; Memory mTest = new Memory(testStr.length()+1); // '+1' remember about extra byte for \0 character! mTest.setString(0, testStr); String testReturn = mTest.getString(0); // you can see that String got properly stored in Memory object System.out.println("String in Memory:"+testReturn); Memory intMem = new Memory(4); // allocating space intMem.setInt(0, 666); // setting allocated memory to an integer Pointer intPointer = intMem.getPointer(0); int int1 = sdll.giveVoidPtrGetInt(Pointer.NULL); // passing null, getting default result System.out.println("giveVoidPtrGetInt(null):" + int1); int int2 = sdll.giveVoidPtrGetInt(intMem); // passing int stored in Memory object, getting it back //int int2 = sdll.giveVoidPtrGetInt(intPointer); causes JVM crash, use memory object directly! System.out.println("giveVoidPtrGetInt(666):" + int2); byte char1 = sdll.giveVoidPtrGetChar(Pointer.NULL); // passing null, getting default result byte char2 = sdll.giveVoidPtrGetChar(mTest); // passing string stored in Memory object, getting first letter System.out.println("giveVoidPtrGetChar(null):" + (char)char1); System.out.println("giveVoidPtrGetChar('ToBeOrNotToBe'):" + (char)char2); >> 

Loading the DLL is only the easiest step.

As it is not really trivial to call a method of a DLL from Java this answer is only a summary of hints what you have to do to call a function from a DLL. The whole story would fill a book. And in fact there are several books about JNI (Java Native Interface).

To call a function in a native library you have to declare a method in your java class as native with the java keyword native . The declaration of this method must not have a body.

The name of the function exported from your DLL must match the following pattern: Java_classname_methodname where classname is the name of the class where you declared the native method methodname .

For example if you declare a native method private native void sayHello() in your class MyClass the name of the DLL’s function would be: Java_MyClass_sayHello

Also keep in mind that the function must be exported from the DLL with the correct calling conventions JNIEXPORT and JNICALL which are defined in the header file jni.h that comes with your JDK (see include folder)

Every function of a DLL to be called from Java also must have two «hidden» arguments as first parameters (JNIEnv *env, jobject obj) . env is a pointer to the calling JVM which allows you callback into the JVM and obj is the object from which the method was called.

So the whole definition of the DLL’s method in our example would be: JNIEXPORT void JNICALL Java_MyClass_sayHello(JNIEnv *, jobject);

Due to these restrictions of JNI a DLL called from your code must be specifially made for your code. To use an arbitrary DLL from Java you usually have to create an adapting DLL with the conventions of JNI that itself loads the «target» DLL and calls the required functions.

To generate the correct headers for your adapter DLL you can use the tool javah shipped with the JDK. This tool will generate the headers to be implemented from your Java code.

Источник

How to call external dll function from java code

I need to call external DLL library function from Java code. I use Netbeans 7.2. My dll’s functions are:

Boolean isValid(string word) List getWords(String word) 

I’m following this example. But I don’t know how declare my dll functions. And I found another link. But it doesn’t work for me.

«It doesn’t work for me» isn’t nearly enough information for us to help you. You need to tell us what you’ve tried, and what the results were. Please read tinyurl.com/so-list

4 Answers 4

I stumbled upon the same problem of «calling DLL from Java» and first was frustrated about the complexity. Yet, there is an elegant solution (might also be interesting for the people over there in the processing.org habitat..) Given the rather «general» form of the question (maybe, downrating is not justified for that), I suppose, a rather easy-going solution would be indicated. In other words, a solution that avoids messing aronud with header files, extra conversions, etc., just as the source code is not necessarily available.

My recommendation for that would be JNA (https://github.com/twall/jna), which basically is a simplifying wrapper around JNI. It works great, type mapping is straightforward (e.g. pchar = lpcstr buffer -> string), though I am using it only towards Windows DLLs and my own C-style DLLs created using Delphi-Pascal. The only thing to consider is that return values should be exported through functions rather than «out» flagged reference variables. The question already points to a linked source that provides an example for that (so, answers around JNI may be misplaced here). Note that the link I provided also contains axamples for the transfer of arrays and pointers.

You will need to use the Java Native Interface (JNI), which is a set of C/C++ functions that allow native code to interface with java code (i.e. receiving parameters from java function calls, returning results, etc). Write a wrapper C library that receive JNI calls and then call your external library.

For instance, the following function invokes a method updateHandlers on a native object (that is stored as long in the Java side).

class MyImpl < void updateHandlers(JNIEnv *env) < this->contentHandler = . ; > > JNIEXPORT void JNICALL Java_package_Classname_updateHandlers0 (JNIEnv *env, jobject obj, jlong ptr) < ((MyImpl*)ptr)->updateHandlers(env); > 

The corresponding declarations in package.ClassName are:

private long ptr; //assigned from JNI public void updateHandlers() < if (ptr==0) throw new NullPointerException(); updateHandlers0(ptr); >private native void updateHandlers0(long ptr); static < try < /*try preloading the library external.dll*/ System.loadLibrary("external"); >catch (UnsatisfiedLinkError e) < /*library will be resolved when loading myjni*/ >System.loadLibrary("myjni"); //load myjni.dll > 

Источник

Оцените статью