Click to See Complete Forum and Search --> : How to import a DLL
Johan A
July 23rd, 1999, 10:15 AM
I have a DLL (no graphics, just pure functions with API calls) called login.dll (win32 created with VC++ 6.0) with one exported function, BOOL SSPLogonUser(LPTSTR, LPTSTR, LPTSTR). I can use this dll with VJ++ 6.0, but I don't want to do that.
I want to use this DLL in sun's JDK1.2, but I can't. Why???
I always get this message, whatever method (load or loadlibrary) I use:
Exception in thread "main" java.lang.UnsatisfiedLinkError: SSPLogonUser
at java.simple.Validation.main(Validation.java:33)
I this a bugg in java, am I not supposed to be able to use a win32 dll together with java 1.2?
Does Java 1.2 have some requirements on the "looks" of a DLL created for win32?
...
private native boolean SSPLogonUser(StringBuffer domain, StringBuffer user,StringBuffer password);
static{
Runtime.getRuntime().load("d:\\classes\\ login.dll");
}
July 26th, 1999, 03:15 AM
If you use System.loadLibrary("nameOfTheDll") the system have to know the path, where to find the library. You may have to add the path to your classpath.
IMHO you can use System.load("completePathToYourDLL").
Johan A
July 26th, 1999, 03:55 AM
Thanks, but that doesn't work either.
The DLL is loaded, but the function within the DLL isn't recognized (UnsatisfiedLinkError: function name).
What's the problem?
July 26th, 1999, 08:11 PM
I was getting the same error. i included the include file in the implementaiton file of the dll and recompiled the dll. it worked. Try it.
Real Gagnon
July 28th, 1999, 12:33 AM
You can't directly use a Win32 dll for Java. You must write a "wrapper" using JNI (Java Native Interface) to act as a bridge between the JVM and the native dll. This is not as simple as it sounds if you are novice in C programming.
The other alternative is to use a third-party universal "wrapper" for win32 dll like CoRoutine from Neva Object technology, see http://www.nevaobject.com/java/index.htm .
Good Luck.
---
Real Gagnon
Java Javascript and PowerBuilder How-to
http://www.tactika.com/realhome
July 29th, 1999, 06:16 AM
Hi Johan,
I'm no expert on JNI but I just read a very good article on it in the March 1999 Java Report.
The way they were doing the library load was
System.loadLibrary("library_name");
JNI figures out which extension to add (.dll if its windows) and it also finds its location some how (probably has to be on the path).
One thing to note, JNI requires you to create an intermediate layer using the javah tool. I think the library you load is made up of the stuff
the javah tool produces and your implementations of these headers. These implementations then call your class functions.
Check out the article for more indepth info.
Effective Java : Native Territory (John Miller Crawford)
Java Report : March 1999
Refs methioned in the article are java.sun.com/products/jdk/1.2/docs/guide/jni/index.html
Hope this this useful.
Cheers, Colin
az99
August 18th, 1999, 12:16 PM
Here are the steps involved in calling c/c++ code
from java(taken from Java Tutorial book):
Step 1: Write the Java Code
The following Javacode segment defines a class named HelloWorld. This class declares one native method, implements a main method, and has a static code segment.
class HelloWorld {
public native void displayHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
Declare a Native Method
You must declare all methods, whether Java methods or native methods, within a class on the Java side. When you write a method implementation in a language other than Java, you must include the keyword native as part of the method's definition within the Java class. The native keyword signals to the Java compiler that the function is a native language function. It is easy to tell that the implementation for the HelloWorld class's displayHelloWorld method is written in another programming language because the native keyword appears as part of its method definition:
public native void displayHelloWorld();
This native method declaration in your Java class provides only the method signature for displayHelloWorld. It provides no implementation for the method. You must provide the implementation for displayHelloWorld in a separate native language source file.
The method declaration for displayHelloWorld also indicates that the method is a public instance method, accepts no arguments, and returns no value. For more information about arguments to and return values from native methods see Interacting with Java from the Native Side .
Load the Library
You compile the native language code that implements displayHelloWorld into a shared library (you will do this in Step 5: Create a Shared Library). The runtime system later loads the shared library into the Java class that requires it. Loading the library into the Java class maps the implementation of the native method to its declaration.
The HelloWorld class uses the System.loadLibrary method. The System.loadLibrary method loads the shared library that will be created when you compile the implementation code. Place this method within a static initializer. The argument to System.loadLibrary is the shared library name. This can be any name that you choose. The system uses a standard, but platform-specific, approach to convert the library name to a native library name. For example, the Solaris system converts the library name "hello" to libhello.so, while a Win32 system converts the same name to hello.dll.
The following static initializer from the HelloWorld class loads the appropriate library, named hello. The runtime system executes a class's static initializer when it loads the class.
static {
System.loadLibrary("hello");
}
Write the Main Method
The HelloWorld class, because it is an application, also includes a main method to instantiate the class and call the native method. The main method instantiates HelloWorld and calls the displayHelloWorld native method.
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
You can see from the code sample that you call a native method in the same manner as you call a regular method: just append the name of the method to the end of the object name, separated with a period ('.'). A matched set of parentheses, (), follow the method name and enclose any arguments to pass into the method. The displayHelloWorld method doesn't take any arguments.Step 2: Compile the Java Code
Use the Java compiler to compile the class that you created in the previous step. Here's the command to use:
javac HelloWorld.java
Step 3: Create the .h File
In this step, you use the javah utility program to generate a header file (a .h file) from the HelloWorld class. The header file provides a C function signature for the implementation of the native method displayHelloWorld defined in that class.
Run javah now on the HelloWorld class that you created in the previous steps.
The name of the header file is the Java class name with a .h appended to the end. For example, the command shown above will generate a file named HelloWorld.h.
By default, javah places the new .h file in the same directory as the .class file. Use the -d option to instruct javah to place the header files in a different directory.
The Function Definition
Look at the header file HelloWorld.h.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
/*
* Class: HelloWorld
* Method: displayHelloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
Step 4: Write the Native Method Implementation
Now, you can finally write the implementation for the native method in a language other than Java.
Note: Back to that "real world," C and C++ programmers may already have existing implementations of native methods. For those "real" methods, you need only ensure that the native method signature matches the signature generated on the Java side.
The function that you write must have the same function signature as the one generated by javah in the HelloWorld.h file in Step 3: Create the .h File. Recall that the function signature generated for the HelloWorld class's displayHelloWorld native method looks like this:
JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *, jobject);
Here's the C language implementation for the native method Java_HelloWorld_displayHelloWorld. This implementation is in the file named HelloWorldImp.c.
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}
The implementation for Java_HelloWorld_displayHelloWorld is straightforward. The function uses the printf function to display the string "Hello World!" and then returns.
The HelloWorldImp.c file includes three header files:
1. jni.h - This header file provides information that the native language code requires to interact with the Java runtime system. When writing native methods, you must always include this file in your native language source files.
2. HelloWorld.h - The .h file that you generated in Step 3: Create the .h File.
3. stdio.h - The code snippet above includes stdio.h because it uses the printf function. The printf function is part of the stdio.h library.
Remember in Step 1: Write the Java Code you used the following method call to load a shared library named hello into your program at runtime:
System.loadLibrary("hello");
Now you are ready to create this shared library.
Step 6: Run the Program
Now run the Java application (the HelloWorld class) with the Java interpreter, as follows:
java HelloWorld
You should see the following output:
Hello World!
Hope this helps
Karim
Philip Reed
October 12th, 1999, 09:58 AM
I didn't get the impression from your first post that you had used the JNIEXPORT and JNICALL #defined constants. Now, you may well know a reason why not to (I think they resolve to _cdecl or _stdcall or one of those modifiers that I can't ever keep straight), but if not I would encourage you to use them. Somehow JNI.H (which must be #included) does some kind of magic to export stuff so that the Java code can find it, as long as you have those defines. So, with something like:
JNIEXPORT jdouble JNICALL Java_avid_winapi_WinAPIFile_writeFile
(JNIEnv *, jobject, jstring, jlong, jobject, jobject);
as your C/C++ prototype, and a similar use of JNIEXPORT and JNICALL before the function body, Java has no problem calling it from
public native double writeFile (String str, long l, Long lOut, Object someObj)
in avid.winapi.WinAPIFile
gymshoe
September 18th, 2000, 04:03 PM
you are not supposed to give the full path with the .dll extension, just give the name of the dll "login" The library loader for windows will append the .dll extension. You need to modify the PATH variable to make sure your .dll can be found by searching the path.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.