I've ran into another issue with the Native interface , it occurs when mixing it with JNI.
Anyone know why the class load fails on the Native Invocatuon side if I include a JNI call on the Java side??
Here's the sequence
1 .Main.cpp -> 2 . MainNativeWindow.cpp (Native Interface) -> 3 . MyWindow.java (create Swing and call Native) -> 4. MyNativeWindow.cpp (get HWND and edit)
1. So the main app is C++.
2. The creates a JVM through the native interface
3. The Java Sides paint is overridden on the C++ side, this gives me a HWND to the Java Canvas.
4. The C++ side then writes to the Java Canvas.
My problem is the combination of the Native invocation and the JNI, if I include the JNI call on the Java side then the Native call to access the Java class fails (it works if I remove the JNI function) !!
Anyone know why the class load fails on the Native Invocatuon side if I include a JNI call on the Java side??
Is there an easier way to get access to the Java Canvas from the C++ side, besides using the Java Paint function to give me access , I've given snippets of the code below
1. and 2. C++ main
#include "MainNativeWindow.h"
//Native Interface
#include <stdio.h>
#include <jni.h>
JavaVM *jvm; /* Pointer to a Java VM */
JNIEnv *env; /* Pointer to native method interface */
int verbose = 1; /* Debugging flag */
int MainNativeWindow::InitJava()
{
JavaVMInitArgs vm_args;
jclass cls;
jmethodID main_methodID, test_methodID = NULL;
jint res;
JavaVMOption options[4];
options[0].optionString = "-Djava.compiler=NONE"; /* disable JIT */
options[1].optionString = "-Djava.class.path=${JDK_HOME}/lib;C:/jsdk1.4.2/_jvm/lib;."; /* user classes */
options[2].optionString = "-Djava.library.path=lib"; /* set native library path */
options[3].optionString = "-verbose:jni"; /* print JNI-related messages */
/* Setup the environment */
vm_args.version = JNI_VERSION_1_4;
vm_args.options = options;
vm_args.nOptions = 4;
vm_args.ignoreUnrecognized = 1;
JNI_GetDefaultJavaVMInitArgs(&vm_args);//REPLACE THIS
res = JNI_CreateJavaVM(&jvm,(void **) &env, &vm_args );//REPLACE THIS
cls = env->FindClass("MyWindow");
if(cls)
{
main_methodID = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");//"([Ljava/lang/String;)V" indicates that the Java mehtod takes an array "[" pf Strings and returns void "V"
if(main_methodID)
{
jstring first_str = env->NewStringUTF("The First String");//create string
jobjectArray args = (jobjectArray)env->NewObjectArray(2,env->FindClass("java/lang/String"), first_str);//new array with 2 elements
env->SetObjectArrayElement(args, 1, first_str);//insert the second string into index 1 of the array
jstring second_str = env->NewStringUTF("The Second String");//create string
env->SetObjectArrayElement(args, 2, second_str);//insert the second string into index 1 of the array
env->CallStaticVoidMethod(cls, main_methodID, args);//pass the array to the Java main method
}
jvm->DestroyJavaVM( );
return 1;
}
int main(int argc, char *argv[])
{
MainNativeWindow *nativewin = new MainNativeWindow();
return nativewin->InitJava();
}
3. JAVA side
import java.awt.*;
import javax.swing.*;
public class MyWindow extends Canvas {
static {
// Load the library that contains the paint code.
System.loadLibrary("MyNativeWindow");
}
// native entry point for Painting
public native void paint(Graphics g);
public static void main( String[] argv ){
Frame f = new Frame();
f.setSize(300,400);
JWindow w = new JWindow(f);
w.setBackground(new Color(0,0,0,255));
w.getContentPane().setBackground(new Color(0,0,0,255));
w.getContentPane().add(new MyWindow());
w.setBounds(300,300,300,300);
w.setVisible(true);
}
}
4. C++ AWT interface (doesn't get here with the JNI in the Java class)
//AWT Native Interface
#include <windows.h>
#include <assert.h>
#include "jawt_md.h"
#include "MyWindow.h"
void DrawSmiley(HWND hWnd, HDC hdc);
HRGN hrgn = NULL;
JNIEXPORT void JNICALL
Java_MyWindow_paint(JNIEnv* env, jobject canvas, jobject graphics)
{
JAWT awt;
JAWT_DrawingSurface* ds;
JAWT_DrawingSurfaceInfo* dsi;
JAWT_Win32DrawingSurfaceInfo* dsi_win;
jboolean result;
jint lock;
// Get the AWT
awt.version = JAWT_VERSION_1_4;
result = JAWT_GetAWT(env, &awt);
assert(result != JNI_FALSE);
// Get the drawing surface
ds = awt.GetDrawingSurface(env, canvas);
if(ds == NULL)
return;
// Lock the drawing surface
lock = ds->Lock(ds);
assert((lock & JAWT_LOCK_ERROR) == 0);
// Get the drawing surface info
dsi = ds->GetDrawingSurfaceInfo(ds);
// Get the platform-specific drawing info
dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
HDC hdc = dsi_win->hdc;
HWND hWnd = dsi_win->hwnd;
//////////////////////////////
// !!! DO PAINTING HERE !!! //
//////////////////////////////
if(hrgn == NULL)
{
RECT rcBounds;
GetWindowRect(hWnd,&rcBounds);
long xLeft = 0; // Use with scaling macros
long yTop = 0;
long xScale = rcBounds.right-rcBounds.left;
long yScale = rcBounds.bottom-rcBounds.top;
hrgn = CreateEllipticRgn(X(10), Y(15), X(90), Y(95));
SetWindowRgn(GetParent(hWnd),hrgn,TRUE);
InvalidateRect(hWnd,NULL,TRUE);
} else {
DrawSmiley(hWnd,hdc);
}
// Free the drawing surface info
ds->FreeDrawingSurfaceInfo(dsi);
// Unlock the drawing surface
ds->Unlock(ds);
// Free the drawing surface
awt.FreeDrawingSurface(ds);
}