Hi all!
First of all I want to refer you to the important articles
http://support.microsoft.com/kb/222092/dehttp://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.htmlLast 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