在C ++中从JNI调用Java Jar代码 [英] Invoking Java Jar code from JNI in C++

查看:59
本文介绍了在C ++中从JNI调用Java Jar代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试模拟此(

I'm trying to emulate this (http://snuggletex.sourceforge.net/maven/xref/uk/ac/ed/ph/snuggletex/samples/MinimalExample.html) code inside my C++ language, in order to obtain natively some LaTeX to MathML conversion of mathematical formulæ, but after the last method invocation, my execution gets aborted

#include <iostream>
#include <string.h>
#include <jni.h>

using namespace std;

#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
#define USER_CLASSPATH "snuggletex-1.2.2/snuggletex-core-1.2.2.jar" /* where Prog.class is */

#define SNUGGLE_ENGINE  "uk/ac/ed/ph/snuggletex/SnuggleEngine"
#define SNUGGLE_INPUT   "uk/ac/ed/ph/snuggletex/SnuggleInput"
#define SNUGGLE_SESSION "uk/ac/ed/ph/snuggletex/SnuggleSession"
#define STRING          "java/lang/String"

JNIEnv *env;
 JavaVM *jvm;
 jint res;

void initJVM() {

#ifdef JNI_VERSION_1_2
 JavaVMInitArgs vm_args;
 JavaVMOption options[1];
 options[0].optionString =
 "-Djava.class.path=" USER_CLASSPATH;
 vm_args.version = 0x00010002;
 vm_args.options = options;
 vm_args.nOptions = 1;
 vm_args.ignoreUnrecognized = JNI_TRUE;
 /* Create the Java VM */
 res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
#else
 JDK1_1InitArgs vm_args;
 char classpath[1024];
 vm_args.version = 0x00010001;
 JNI_GetDefaultJavaVMInitArgs(&vm_args);
/* Append USER_CLASSPATH to the default system class path */
 sprintf(classpath, "%s%c%s",
vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
 vm_args.classpath = classpath;
 /* Create the Java VM */
 res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
#endif /* JNI_VERSION_1_2 */


}

void closeJVM() {
    jvm->DestroyJavaVM();
}


jstring JNU_NewStringNative(const char *str)
{
     jstring result;
     jbyteArray bytes = 0;
     jclass Cstr;
     int len;

     len = strlen(str);
     bytes = (env)->NewByteArray( len);
     Cstr = (env)->FindClass(STRING);
     if (bytes != NULL) {
        jmethodID mid;
         (env)->SetByteArrayRegion(bytes, 0, len,(jbyte *)str);
         mid = env->GetStaticMethodID(Cstr, "<init>", "([B)V");
         result = (jstring) (env)->NewObject(Cstr,mid,bytes);
         (env)->DeleteLocalRef(bytes);
         return result;
     } /* else fall through */
     return NULL;
}

int parse_latex(char* input) {

       jclass engine, Cinput, Csession;
 jmethodID mid;
 jstring jstr;
 jclass stringClass;
 jobjectArray args;
 jstring latex = JNU_NewStringNative(input);
 jstring result;



      engine = env->FindClass(SNUGGLE_ENGINE);
      Cinput = env->FindClass(SNUGGLE_INPUT);
      Csession = env->FindClass(SNUGGLE_SESSION);

      if (engine==NULL) return -1;
      mid = env->GetStaticMethodID(engine, "<init>", "()V");
      jobject snuggle = env->NewObject(engine, mid);

      mid = env->GetStaticMethodID(engine, "createSession", "()V");
      jobject session = env->NewObject(engine, mid);


      //if (cls==NULL) return -1;
      mid = env->GetStaticMethodID(Cinput , "<init>", "(Ljava/lang/String;)V");
      jobject input_elem = env->NewObject(Cinput, mid,latex);

      mid =  env->GetStaticMethodID(Csession , "parseInput", "(Luk/ac/ed/ph/snuggletex/SnuggleInput;)V");
      env->CallNonvirtualVoidMethod(session, Csession, mid, input_elem);

      printf("obtaining method\n");
      mid =  env->GetMethodID(Csession , "buildXMLString", "()Ljava/lang/String;");
      printf("calling method\n");
      try {
     result = (jstring)env->CallObjectMethod(session, mid);
     printf("ok\n");
      } catch (...) {
      jthrowable exc;
      exc = (env)->ExceptionOccurred();
      if (exc) {
      env->ExceptionDescribe();
      //Returns java.lang.NullPointerException
       }
      }




    return 0;
}



int main() {

    int resint;
    initJVM();

    resint = parse_latex("$$5^2$$");

    closeJVM();
    return resint;

}

我正在使用:

 g++ -I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/linux -L/usr/lib/jvm/java-1.5.0-gcj-4.4/jre/lib/amd64/ -L/usr/lib/jvm/java-1.5.0-gcj-4.4/jre/lib/amd64/client -ljvm -Wl,-rpath,/usr/lib/jvm/java-1.5.0-gcj-4.4/jre/lib/amd64/client -lstdc++ runner.cpp

我在哪里错了?预先感谢

Where am I wrong? Thanks in advance

编辑

据我所知,env->CallObjectMethod(session, mid);//Aborted会引发C ++异常, 尤其是java.lang.NullPointerException

As far as I can see, env->CallObjectMethod(session, mid);//Aborted throws a C++ exception, and particularly a java.lang.NullPointerException

解决方案

#include <iostream>
#include <string.h>
#include <jni.h>
#include <stdlib.h>

using namespace std;

#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
#define USER_CLASSPATH "snuggletex-1.2.2/snuggletex-core-1.2.2.jar" /* where Prog.class is */

#define SNUGGLE_ENGINE  "uk/ac/ed/ph/snuggletex/SnuggleEngine"
#define SNUGGLE_INPUT   "uk/ac/ed/ph/snuggletex/SnuggleInput"
#define SNUGGLE_SESSION "uk/ac/ed/ph/snuggletex/SnuggleSession"
#define STRING          "java/lang/String"

JNIEnv *env;
 JavaVM *jvm;
 jint res;

void initJVM() {

#ifdef JNI_VERSION_1_2
 JavaVMInitArgs vm_args;
 JavaVMOption options[1];
 options[0].optionString =
 "-Djava.class.path=" USER_CLASSPATH;
 vm_args.version = 0x00010002;
 vm_args.options = options;
 vm_args.nOptions = 1;
 vm_args.ignoreUnrecognized = JNI_TRUE;
 /* Create the Java VM */
 res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
#else
 JDK1_1InitArgs vm_args;
 char classpath[1024];
 vm_args.version = 0x00010001;
 JNI_GetDefaultJavaVMInitArgs(&vm_args);
/* Append USER_CLASSPATH to the default system class path */
 sprintf(classpath, "%s%c%s",
vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
 vm_args.classpath = classpath;
 /* Create the Java VM */
 res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
#endif /* JNI_VERSION_1_2 */


}

void closeJVM() {
    jvm->DestroyJavaVM();
}


jstring JNU_NewStringNative(const char *str)
{
 jclass strClass = env->FindClass("java/lang/String"); 
 jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); 
 jstring encoding = env->NewStringUTF("GBK"); 

jbyteArray bytes = env->NewByteArray(strlen(str)); 
env->SetByteArrayRegion(bytes, 0, strlen(str), (jbyte*)str); 
return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
}


const char * parse_latex(char* input) {

    jclass engine, Cinput, Csession;
    jmethodID mid;
    jstring jstr;
    jclass stringClass;
    jobjectArray args;
    jstring latex = JNU_NewStringNative(input);
    jstring result;



    engine = env->FindClass(SNUGGLE_ENGINE);
    Cinput = env->FindClass(SNUGGLE_INPUT);
    Csession = env->FindClass(SNUGGLE_SESSION);

    // SnuggleEngine engine = new SnuggleEngine();
    mid = env->GetMethodID(engine, "<init>", "()V");
    jobject snuggle = env->NewObject(engine, mid);

    // SnuggleSession session = engine.createSession();
    mid = env->GetMethodID(engine, "createSession", "()L"SNUGGLE_SESSION";");
    jobject session = env->CallObjectMethod(snuggle, mid);

    // SnuggleInput input = new SnuggleInput("$$ x+2=3 $$");
    mid = env->GetMethodID(Cinput , "<init>", "(Ljava/lang/String;)V");
    jobject input_elem = env->NewObject(Cinput, mid, latex);

    // session.parseInput(input);
    mid = env->GetMethodID(Csession , "parseInput", "(L"SNUGGLE_INPUT";)Z");
    env->CallBooleanMethod(session, mid, input_elem);

    // String xmlString = session.buildXMLString();
    mid = env->GetMethodID(Csession , "buildXMLString", "()Ljava/lang/String;");
    result = (jstring) env->CallObjectMethod(session, mid);

    printf("here\n");
    const jbyte *str = (jbyte *)(env)->GetStringUTFChars(result, NULL);

    return ((char*)str);


    return 0;
}



int main() {

    const char* resint;
    initJVM();

    resint = parse_latex("$$ x+2=3 $$");
    if (resint) printf("%s\n", resint); else printf("error\n");

    closeJVM();
    return (resint!=0);

}

推荐答案

您调用了错误的方法.

// SnuggleEngine engine = new SnuggleEngine();
mid = env->GetMethodID(engine, "<init>", "()V");
jobject snuggle = env->NewObject(engine, mid);

// SnuggleSession session = engine.createSession();
mid = env->GetMethodID(engine, "createSession", "()L"SNUGGLE_SESSION";");
jobject session = env->CallObjectMethod(snuggle, mid);

// SnuggleInput input = new SnuggleInput("$$ x+2=3 $$");
mid = env->GetMethodID(Cinput , "<init>", "(Ljava/lang/String;)V");
jobject input_elem = env->NewObject(Cinput, mid, latex);

// session.parseInput(input);
mid = env->GetMethodID(Csession , "parseInput", "(L"SNUGGLE_INPUT";)Z");
env->CallBooleanMethod(session, mid, input_elem);

// String xmlString = session.buildXMLString();
mid = env->GetMethodID(Csession , "buildXMLString", "()Ljava/lang/String;");
result = (jstring) env->CallObjectMethod(session, mid);

我没有测试.希望它能起作用!

I didn't test it. Hope it works!

这篇关于在C ++中从JNI调用Java Jar代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆