Skip to content

Instantly share code, notes, and snippets.

@OpenGamma-Blog
Created September 28, 2012 11:14
Show Gist options
  • Save OpenGamma-Blog/3799238 to your computer and use it in GitHub Desktop.
Save OpenGamma-Blog/3799238 to your computer and use it in GitHub Desktop.
slf4j example 3
// global cache
extern JavaVM JVMCache; // global JVM pointer cache
static jclass wrappedClass = NULL; // holds the class that wraps the native code
static jclass slf4jLoggerClass = NULL; // holds the slf4j class
static jfieldID loggerFieldID = 0; // the ID of the Logger field "log" (this is a static reference set each time by the classloader)
static jmethodID loggerMethodID = 0; // the ID of the logger method (it's the ID obtained from the slf4j class (interface), the vtable is used to look up the particular method in the object which instantiated from this class)
// C code for the initialisation (we leave out exception handling for brevity)
#ifdef __cplusplus
extern "C"
#endif
/*
* This code is called on instantiation and is part of the static block of the wrapper
* Class: com_opengamma_maths_nativewrappers_OGNativeCodeWrapper
* Method: initialiseLogger
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_opengamma_maths_nativewrappers_OGNativeCodeWrapper_initialiseLogger(JNIEnv * env, jclass theClass)
{
jint jStatus = 0;
JNIEnv *envPtr; // will hold env ptr
jclass tmpClass = NULL; //temporary class holder
// grab env ptr
jStatus=(*JVMcache)->AttachCurrentThread(JVMcache, (void **)&envPtr, NULL);
if(jStatus){
//handle error
}
// find OGNativeCodeWrapper class
tmpClass = NULL;
tmpClass = (*envPtr)->FindClass(envPtr,"com/opengamma/maths/nativewrappers/OGNativeCodeWrapper"); // find class
if(tmpClass==NULL) {
//handle error
}
wrappedClass=NULL; // we set this to 0 so the global reference is 0'd out so we can catch fail if the classloader reloads
wrappedClass = (jclass)((*envPtr)->NewGlobalRef(envPtr,tmpClass));
if(wrappedClass==NULL){
//handle error
}
// find logger class
tmpClass = NULL;
tmpClass=(*envPtr)->FindClass(envPtr,"org/slf4j/Logger");
if(tmpClass==NULL) {
//handle error
}
slf4jLoggerClass=NULL; // we set this to 0 so the global reference is 0'd out so we can catch fail if the classloader reloads
slf4jLoggerClass = (jclass)((*envPtr)->NewGlobalRef(envPtr,tmpClass));
if(slf4jLoggerClass==NULL) {
//handle error
}
loggerFieldID = 0; // we set this to 0 so the global reference is 0'd out so we can catch fail if the classloader reloads
loggerFieldID = (*envPtr)->GetStaticFieldID(envPtr, wrappedClass, "log", "Lorg/slf4j/Logger;");
if (loggerFieldID == 0) {
//handle error
}
loggerMethodID = 0; // we set this to 0 so the global reference is 0'd out so we can catch fail if the classloader reloads
loggerMethodID = (*envPtr)->GetMethodID(envPtr, slf4jLoggerClass, "warn", "(Ljava/lang/String;)V");
if (loggerMethodID == 0) {
//handle error
}
}
// implement fortran f_log_buffered
#define F_LOG_BUFFERED_F77 F77_FUNC(f_log_buffered,F_LOG_BUFFERED)
#ifdef __cplusplus
extern "C"
#endif
void F_LOG_BUFFERED_F77(char *, int*);
// by virtue of static initialisation the global pointers to the static classes, ids and methods will be set before this is called
#ifdef __cplusplus
extern "C"
#endif
void F_LOG_BUFFERED_F77(char * c, int * length)
{
// points to an object instantiated from a slf4j logger class (it's an interface, who knows what the object will be!)
jobject theLogger = NULL;
jint jStatus = 0; // status for jvm grabbing calls
char * messageBuffer = NULL; // buffer for the message before its UTF8ilised
JNIEnv *envPtr; // will hold env ptr
jstring javaMessage = NULL; // will hold the hava message for slf4j
// grab env ptr
jStatus=(*JVMcache)->AttachCurrentThread(JVMcache, (void **)&envPtr, NULL);
if(jStatus){
//handle error
}
// all we know is that the logger implements a slf4j interface so we have to get a pointer to the instantiated version
theLogger = (*envPtr)->GetStaticObjectField(envPtr, wrappedClass, loggerFieldID);
if(theLogger==NULL){
//handle error
}
// create a buffer for the message
messageBuffer = (char *) malloc(*length+1);
if(messageBuffer == NULL) {
//handle error
}
// copy in the message based on the length given by Fortran len(log_message)
memcpy(messageBuffer,log_message,(size_t)*length);
// nul terminate
*(messageBuffer+*length)='\0';
// knock out high bits/bits out of UTF8 land, worst case things'll just look a bit funny.
size_t i;
for(i=0;i<*length;i++)
{
*(messageBuffer+i)&=0x7f;
}
// create a string from modified UTF8
javaMessage = (*envPtr)->NewStringUTF(envPtr,messageBuffer);
if(javaMessage == NULL) {
//handle error
}
// call the method
(*envPtr)->CallVoidMethod(envPtr, theLogger, loggerMethodID, javaMessage); // we've no idea if this worked, it returns void
// delete reference to the java string as it's been shoved in the log
(*envPtr)->DeleteLocalRef(envPtr,javaMessage);// we've no idea if this worked, it returns void
// free the message buffer
free(messageBuffer);
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment