Author Topic: Calling PE DLL from Java  (Read 12767 times)

nobody

  • Guest
Calling PE DLL from Java
« on: December 17, 2007, 12:45:32 PM »
Hi,
normally I compile my nasm projects to a PE DLL (Windows) and let them call by C# Programs using i.e. LoadLibrary(EX) and GetProcessAddress.
Now, we have to call such a PE DLL from Java. There also exist a LoadLibrary function but (perhaps) something like GetProcessAddress is missing. Instead you can find a lot of examples on the internet how to "import" C++ object DLLs using the JNI native interface.
Does anybody have an idea (or eben example code) how to load and use our PE function DLLs?
Thanks,
Martin

nobody

  • Guest
Re: Calling PE DLL from Java
« Reply #1 on: December 17, 2007, 09:34:31 PM »
Hi, me again!
I solved the problem - finally, stuff is simple:
1. your nasm functions have to have 2 additional JNI parameters "JNIEnv" and "jobject" - but can ignore them ...
2. adjust stack correction accordingly - 2 more 4 byte pointers in the ret opcode
3. stdcall is mandatory
4. exposed symbols have to maintain java name convention - export your function symbol "test" as "Java_Classname_test", where Classname is the name of the calling java class importing your function "test"
That is all ;-)
If somebody is interesed in details I can provide some simple example code.
Martin

nobody

  • Guest
Re: Calling PE DLL from Java
« Reply #2 on: December 21, 2007, 05:06:57 AM »
If it's not too much trouble, I would like to see some simple example code for this.  Doesn't have to be elaborate, just enough to get the concept across.  Thanks martin!

mene mene tekel

  • Guest
Re: Calling PE DLL from Java
« Reply #3 on: December 23, 2007, 01:06:23 PM »
Hi all!

First of all I want to refer you to the important articles

http://support.microsoft.com/kb/222092/de
http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html

Last one specifies the very deep details in handling simple as well as building up complex data structure being
not directly supported by the Java Native Interface (JNI).

Main problem in those descriptions is that they all assume you will work top down, means first you design and
write your java class, then generate a header file from that using javah.exe and lastly give all this to your
C++ programmer to write the native stuff ...

But typically you face the problem in the other way around: You *have* an native nasm based PE DLL working
fine and you want to access them in a java application - so you’re working bottom up.
As in .net also JNI provides a LoadLibrary call, but different to .net JNI doesn't offer a GetProcAddress call
to get rid of a function entry point. Instead JNI assumes that the native dll supports the JNI "name conventions".
I call it "name conventions" because from the structure of generated include header files like

extern "C" {
/*
 * Class:     Evation
 * Method:    callnative
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_Evation_callnative
  (JNIEnv *, jobject, jint);
}

we learn, that classes and methods they talk about, is nothing more than ordinary C-function calls
(but with _stdcall calling conventions!) and name convention for the native function name exposed by your
native dll as Prefix_Classname_Functionname

Prefix:      Java      (fix prefix)
Classname:   Evation      (my dummy class name)
Functionname:   callnative   (my dummy function name)

In your Java code this looks like:

public class Evation{
   public native int callnative(int);

static {
      System.loadLibrary("nasmPeDll");
   }

public static void main(String args[]) {
      System.out.println(new Evation().callnative(7));
   }
}

Thus, beside the name convention - see, in Java the native function simply is declared as "callnative" - the JNI
provides two additional arguments "JNIEnv*" and "jobject" to the callee. Therefore, if you cannot adopt your
nasm code accordingly, you have to write a small wrapper around your native dll, which
 - ignores the 1st and 2nd function parameter
 - exposes the function symbols accordingly to the name convention mentioned above

To work with written Java code your callnative could look like (standard dll entry point omitted here):


global      callnative
export      callnative    Java_Evation_callnative   resident


%define     iValue      ebp+16                  ;input value
%define     pObj        ebp+12                  ;jobject = UInt32
%define     pEnv        ebp+8                   ;JNIEnv  = UInt32

callnative:
            push  ebp                           ;Save absolut ebp and redefine
            mov   ebp,  esp                     ; as relative stack base

mov   eax,  dword [iValue]      ;Some dummy
            inc   eax            ; calculations ...

mov   esp,  ebp                     ;Local variable stack
            pop   ebp                           ; restore absolut ebp
            ret   3*4                           ;Return

The export statement takes care of the name convention
The 1st argument pEnv as well as the 2nd argument pObj are "skipped"
The 3rd ff. arguments are handled as the 1st ff. arguments of the native function
The ret statement takes care of these 2 additional arguments
The calling convention is _stdcall
(A wrapper would similar)

Compiling with:
nasmw.exe -fobj nasmPeDll.asm
alink.exe -oPE -dll -subsys con -entry nasmPeDllEntry -o nasmPeDll.dll nasmPeDll.obj

Thats it!

Have fun,
Martin