2

I have searched this through stackoverflow and in the internet and haven't found yet an answer.

I have a SDK of a fingerprint reader which I haven't got the source code, meaning I can't change it.

It has a few methods I need to access, which interface I will list below (from RS_API.h):

REALSCANSDK_API int __stdcall RS_InitSDK( const char* configFileName, int option, int* numOfDevice );
REALSCANSDK_API int __stdcall RS_InitDevice( int deviceIndex, int*deviceHandle );
REALSCANSDK_API int __stdcall RS_SetCaptureMode( int deviceHandle, int captureMode, int captureOption, bool withModeLED );
REALSCANSDK_API int __stdcall RS_SetViewWindow( int deviceHandle, HWND windowHandle, RECT drawRectangle, bool autoContrast );
REALSCANSDK_API int __stdcall RS_TakeImageDataEx( int deviceHandle, int timeout, int fingerIndex, bool withLED, unsigned char** imageData, int* imageWidth, int* imageHeight );

I managed to convert all of them to Delphi, but I also wanted to access it from a java app.

My prototype is like this:

public class Leitor {
    public native int  RS_InitSDK(String configFileName, int option, int numOfDevice );

    public static void main(String[] args) {
        Leitor leitor= new Leitor();
        leitor.RS_InitSDK(null, 0, 0);
    }
  static 
  {
    System.load("C:\\temp\\SDKSuprema\\SDK\\RS_SDK.dll");    
  }
}

The load bit works fine (I believe it means that it can find the dll file), but when it runs the native method it throws the exception:

Exception in thread "main" java.lang.UnsatisfiedLinkError: leitor.Leitor.RS_InitSDK(Ljava/lang/String;II)I at leitor.Leitor.RS_InitSK(Native Method) at leitor.Leitor.main(Leitor.java:14)

If I rename the dll it changes the error to "Can't load library", so I think the problem is the mapping of the methods.

I also couldn't find how to map a pass by reference parameter to be called from Java. The only solution was by changing the dll to return a structure instead of a single result, but this isn't possible, as I can't change the code.

A second problem will be to send the window handle from swt to the JNI native method...

Any help is greatly welcome!

Emerson
  • 935
  • 4
  • 13
  • 27
  • Looks like what you are looking for is [JavaCPP](http://code.google.com/p/javacpp/) or one of the other tools I list on that page. – Samuel Audet Nov 16 '12 at 02:32

2 Answers2

2

You need to write explicit glue code that accepts parameters as Java objects and converts them to the representation the existing C entry points expect. The JVM will not do this for you by itself.

Read the JNI specification to learn how to write this glue code.

In particular, in order to match your Java declaration, the JNI entry point must be named package_name_here_Leitor_RS_1InitSDK or package_name_here_Leitor_RS_1InitSDK__Ljava_lang_String_2II; see the "Resolving Native Method Names" section of chapter 2 of the spec. This function must take some extra arguments in front of the Java visible ones; see "Native Method Arguments" in the spec.

In the method you get passed the string as a jstring value, which you must use the GetStringUTFChars helper function from the JVM to convert to a C string.

For pass-by-reference parameters, you will need to find a way to simulate them that makes sense to the calling Java code, such as by passing an object whose fields are assigned by your JNI code, or (quickly and dirtily) passing an int[] whose first element gets assigned by your JNI code.

hmakholm left over Monica
  • 23,074
  • 3
  • 51
  • 73
  • I've always wrapped C++ libraries in my own glue classes when calling them from Java. It insulates you from their quirky behaviours and gives you full control over exposing only the pieces you need to use. – Kieveli Nov 09 '12 at 17:29
1

You need to create c/c++ glue code to implement the java methods, calling javah with a class will create a header declaring the native counterpart to java methods marked as native.

If you do not want to write c/c++ you can use JNA to map java code to existing c methods and structs in most cases.

Community
  • 1
  • 1
josefx
  • 15,506
  • 6
  • 38
  • 63