Original Post
Hello everybody, Well I'm working on a game in Java (well for bloody too long in fact now!-its begining to feel more like vaporware than anything! [lol]) and its going well so far. One of the things I would like to do is implement my own little timer for doing stuff like frame rate independent movement and such.. Anyhow the long and the short is that I'm attempting write this in C and compile it to a native .dll which can then be used in my java program through the JNI. Why am I not using System.nanoTime() ? Well I won't go into that here.. Even if you want to call me stupid for doing this, I still see this as a little chance to learn about the JNI, something which could be handy in future. Ok, so here's what I've done so far: I created my C code with all the timer functions, using the naming and function conventions as described in the JNI docs. I'm using DevC++ for my IDE so i selected 'compile as win32 dll' under project options and then compiled the code. No problems there.. The .dll is generated as expected with no compile time errors or warnings.. Good.. So I then made my java interface to the C functions inside a new class called 'NativeTimer'. The methods are all declared with the correct paramters and returns etc.. and use the 'native' modifier. I also got the class to load the native library upon its initialisation using the System.loadLibrary() method. This much works, I can confirm. Upon removing the .dll from my java project directory, an error is generated saying that the library could not be located- so it IS loading the .dll as expected. However, whenever I try to invoke any of the methods in the 'NativeTimer' class I get a 'UnsatisfiedLinkError' from the JVM meaning that it could not find the native methods.. Here I am lost.. I've looked at the JNI docs and my naming *appears* to be correct, i'll say that cautiously now.. I've also looked at some tutorials on the net and nothing appears to be out of order.. I have no idea where I am going wrong.. It has to be something to do with the function names, but I cannot figure out what exactly it is.. Any ideas ? Heres the java code for the NativeTimer class: And heres the C code which compiles into the .dll:
class NativeTimer
{
// Function prototypes
static native void init(); // initialise native timer
static native void update(); // update and save time between last call to update in seconds
static native double frameTime(); // return last frame time in seconds
// Static initialisation
static { System.loadLibrary("NativeTimer"); }
}
/*******************************************************************************
Native timer: simple native timer for java. Uses Win32 functions to retrieve
time and performance counter. This code is *not* portable, but could be
modified to support other platforms
Compile as a DLL
*******************************************************************************/
extern "C"
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Includes
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define WIN32_LEAN_AND_MEAN // Trim junk from windows
#include <windows.h> // windows library
#include "JNI.h" // jni header file
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Variables
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
long double clockFrequency = 2000000.0; // Frequency of system clock
long double lastFrameTime = 0; // Time the last frame took in seconds
__int64 lastClockTime = 0; // Clock timer last time it was invoked
__int64 currentClockTime = 0; // Current clock timer value
/*******************************************************************************
Name: init
Purpose: Initialises the timer. Querys windows for how fast the system clock is.
This is important because a 1GHz machine's clock will not run at the
same speed as a 2Ghz machine- and the timing will be messed up!
Parameters: Pointer to JNI environment
Returns: None
*******************************************************************************/
JNIEXPORT void JNICALL Java_NativeTimer_init( JNIEnv * env )
{
// Get clock Frequency from windows
LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency);
// Get number of clocks as a 64-bit integer
unsigned __int64 numClocks = *((unsigned __int64*)(&frequency));
// Calculate clock frequency in seconds
clockFrequency = ((long double)(1.0)) / ((long double)(numClocks));
}
/*******************************************************************************
Name: update
Purpose: Updates the timer and calculates how long the last frame took in
seconds. We can use this to adjust movement based on how fast or not
the game is running.
Parameters: Pointer to JNI environment
Returns: None
*******************************************************************************/
JNIEXPORT void JNICALL Java_NativeTimer_update( JNIEnv *env )
{
// Get the current clock time
LARGE_INTEGER clock; QueryPerformanceCounter(&clock);
// Save clock time as a long
unsigned __int64 currentClock = *((unsigned __int64*)(&clock));
// Get the amount of clocks between the last invocation of the QueryPeformanceCounter
// function and this invocation. Make sure this figure is positive
__int64 frameClocks = currentClock - lastClockTime;
// Divide the number of clocks by the clock frequency to obtain a frame
// time in seconds. Save this figure.
lastFrameTime = frameClocks * clockFrequency;
// Save the current clock time for the next invocation of this function
lastClockTime = currentClock;
}
/*******************************************************************************
Name: frameTime()
Purpose: Returns the number of seconds the last frame took.
Parameters: Pointer to JNI environment
Returns: Double representing the time in seconds the last frame took
*******************************************************************************/
JNIEXPORT jdouble JNICALL Java_NativeTimer_frameTime( JNIEnv *env )
{
return (double)lastFrameTime;
}
} // end of extern "C"