2016-04-16 13 views
0

Ich habe Anforderung, Frühling mit etwas gebürtigem Code C zu schreiben und ich bin neu zu Frühling und habe keine Idee darüber, wenn jemand Erfahrung hat, um Frühling mit JNI zu integrieren, dann teilen Sie bitte mit mir.Wie konfiguriere ich den Frühling mit jni?

Vielen Dank im Voraus.

Antwort

1

Die Frage ist ziemlich vage, aber ich kann ein paar Ratschläge aus der Arbeit, die ich in der Vergangenheit getan habe, anbieten.

  1. Vergessen Sie die Integration mit "Spring". Konzentrieren Sie sich auf die Integration mit Java und lassen Sie Spring Ihnen später helfen.
  2. Seien Sie sehr, sehr vorsichtig mit der Typ und Speicherzuweisung in C
  3. Here ‚s ein Buch über JNI, die ich ungemein hilfreich, wenn ich daran gearbeitet wurde. Es ist ein bisschen altmodisch, aber immer noch gültig
  4. Ich habe den Großteil der Arbeit in C und dann in einer einfachen Methode Hook auf Java gepatcht. Auf diese Weise habe ich den größten Teil der Integration mit dem vorhandenen Code in seiner Muttersprache durchgeführt.
  5. Geben Sie Ihrem C-Code eine Hauptmethode, mit der Sie den C-Code unabhängig von Java testen können. Dann können Sie Ihre C-Datei als eine Bibliothek (dll/so) und eine ausführbare Datei kompilieren. Die ausführbare Datei kann mit Argumenten aufgerufen werden, um die Aufrufe bestehender Aufrufe zu testen.

Der allgemeine Prozess ist.

Java End

public class statusBlock { 
    /* A Java representation of a Status Block */ 
    private long errcode = 0; 
    private long errref = 0; 
    private String errmsg = ""; 
    private long[] TmidArray; 
    private long evt_id = 0; 
    private short IgViolation_severity = 0; 
} 

public class MyFunkyJNIClass { 
    private Object response; 

    /** 
    * To generate the C-header for a native call use: javah -jni 
    * example.package.MyFunkyJNIClass from target/classes folder. 
    */ 
    private native int nativeExecuteFunction(int callType, Object payload, Object response); 

    public MyFunkyJNIClass() { 
     System.loadLibrary("theCLibrary"); 
    } 
} 

Im Beispiel oben ich die C-Seite des Code System.loadLibrary laden und definieren einige Felder, die ich von meinem C-Code versehen können. Zur Ausführung rufen Sie einfach die native Funktion nativeExecuteFunction(1, "my payload", respObject); Auf der C-Seite kann ich das erste Argument verwenden, um zu wählen, was zu tun ist. Es vereinfacht meine Probleme zu der Zeit

C Side

JNIEXPORT jint JNICALL Java_example_package_MyFunkyJNIClass_nativeExecuteFunction(JNIEnv *env, jobject this, jint CallType, jobject Payload) 
{ 
    // **** JNI Specific declarations for mapping **** 
    jclass   cls, cls2, cls3; 
    jmethodID  mid, mid2; 
    jfieldID  fid; 
    jint   rc = 0; 
    jsize   js = 0; 
    jbyte   jb; 
    jobject   jobj, jobj2, jro; 
    jobjectArray jobjArray, jobjArray2; 

    _svc_results results; 

    switch ((int)CallType) 
    { 
    case CALLTYPE1:  // 1 
     DEBUG_PRINT("JNI Call Type 1 in progress...\n"); 
     // JNI mapping happens here 
     stat = DoSomethingInC(args, &results); 

     // Map from C structure (_statblk) to Java object 
     if (stat == SUCCESS) { 
      DEBUG_PRINT("\tMapping from C structure (_statblk) to Java object\n"); 

      cls = (*env)->FindClass(env, "Lexample/package/statusBlock;"); 
      mid = (*env)->GetMethodID(env, cls, "<init>", "()V"); if (mid == NULL) return -1; 
      jro = (*env)->NewObject(env, cls, mid); if (jro == NULL) return -1; 

      fid = (*env)->GetFieldID(env, cls, "errcode","I"); if (fid == NULL) return -1; 
      (*env)->SetIntField(env, jro, fid, (jint)results.statblk.errcode); 
      DEBUG_PRINT("\t\tMapped errcode: %d\n",results.statblk.errcode); 

      fid = (*env)->GetFieldID(env, cls, "errref","I"); if (fid == NULL) return -1; 
      (*env)->SetIntField(env, jro, fid, (jint)results.statblk.errref); 
      DEBUG_PRINT("\t\tMapped errref: %d\n",results.statblk.errref); 

      fid = (*env)->GetFieldID(env, cls, "errmsg","[B"); if (fid == NULL) return -1; 
      jobj = (*env)->NewByteArray(env, MAX_ERR); 
      (*env)->SetByteArrayRegion(env, (jbyteArray)jobj, 0, MAX_ERR, (jbyte*)results.statblk.errmsg); 
      (*env)->SetObjectField(env, jro, fid, jobj); 
      (*env)->DeleteLocalRef(env, jobj); 
      DEBUG_PRINT("\t\tMapped errmsg: %s\n",results.statblk.errmsg); 

      fid = (*env)->GetFieldID(env, cls, "TmidArray","[I"); if (fid == NULL) return -1; 
      jobj = (*env)->NewIntArray(env, (jsize)results.statblk.TmidArray.TmidArray_len); 
      (*env)->SetIntArrayRegion(env, (jintArray)jobj, 0, 
             (jsize)results.statblk.TmidArray.TmidArray_len, 
             (jint*)results.statblk.TmidArray.TmidArray_val); 
      (*env)->SetObjectField(env, jro, fid, jobj); 
      (*env)->DeleteLocalRef(env, jobj); 
      DEBUG_PRINT("\t\tMapped TmidArray\n"); 

      fid = (*env)->GetFieldID(env, cls, "evt_id","I"); if (fid == NULL) return -1; 
      (*env)->SetIntField(env, jro, fid, (jint)results.statblk.evt_id); 
      DEBUG_PRINT("\t\tMapped evt_id: %d\n",results.statblk.evt_id); 

      cls = (*env)->GetObjectClass(env, this); 
      fid = (*env)->GetFieldID(env, cls, "response","Ljava/lang/Object;"); if (fid == NULL) return -1; 
      (*env)->SetObjectField(env, this, fid, jro); 

      DEBUG_PRINT("\tMapping from C structure (_statblk) to Java object - DONE\n"); 
     } else { 
      DEBUG_PRINT("JNI Call Type 1 in progress... Returning Error: %d\n", stat); 
      return (jint)stat; 
     } 

     /* Free our native memory */ 
     cls = (*env)->GetObjectClass(env, Payload); 
     fid = (*env)->GetFieldID(env, cls, "message","Ljava/lang/String;"); if (fid == NULL) return -1; 
     jobj = (*env)->GetObjectField(env, Payload, fid); 
     GPS_Free(results.statblk.TmidArray.TmidArray_val); 
     GPS_Free(results.statblk.ErrorArray.ErrorArray_val); 
     DEBUG_PRINT("JNI RTP Posting in progress... DONE\n"); 
     break; 
    case PING:   // 2 
     DEBUG_PRINT("No Java to C mapping required\n"); 
     DEBUG_PRINT("JNI Ping in progress...\n"); 
     stat = doPing(); 

     DEBUG_PRINT("No C to Java mapping required\n"); 
     // Stop null pointer exception if client tries to access the response object. 
     cls = (*env)->FindClass(env, "Lexample/package/EmptySerializableClass;"); 
     mid = (*env)->GetMethodID(env, cls, "<init>", "()V"); if (mid == NULL) return -1; 
     jro = (*env)->NewObject(env, cls, mid); if (jro == NULL) return -1; 

     cls = (*env)->GetObjectClass(env, this); 
     fid = (*env)->GetFieldID(env, cls, "response","Ljava/lang/Object;"); if (fid == NULL) return -1; 
     (*env)->SetObjectField(env, this, fid, jro); 
     DEBUG_PRINT("JNI Ping in progress... DONE\n"); 

     return (jint)rpc_stat; 
     break; 
    default: 
     fprintf(stderr,"Unknown call type\n"); 
     rc = -1; 
     break; 
    } 

    return rc; 
} 

könnte ich weiter und weiter gehen, aber es dauert nur ein wenig sorgfältige Lektüre dieses Buches.

Es muss nicht wirklich eine weitere Integration mit Spring sein. Sie könnten eine @Component oder @Service Annotation auf die MyFunkyJNIClass kleben.

Ich hoffe, dass dies eine Hilfe für Sie ist.

+0

Vielen Dank !! die von dir zur Verfügung gestellte Information ist wirklich nützlich für mich, bis ich an diesem Punkt im Nebel herumstreune, aber jetzt kann ich Dinge aus kristallklarem Glas sehen. –

Verwandte Themen