我要求将spring与一些用C语言编写的本机代码集成在一起,如果有人有将Spring与JNI集成的经验,那么我对它不熟悉并且对它没有任何想法,请与我分享。
提前致谢。
答案 0 :(得分:1)
这个问题很模糊,但我可以提供一些我过去所做工作的建议。
一般过程是。
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");
}
}
在上面的示例中,我使用System.loadLibrary加载代码的C端,并定义一些我可以从C代码填充的字段。要执行只调用 native 函数nativeExecuteFunction(1, "my payload", respObject);
在C端,我可以使用第一个参数来选择要执行的操作。 当时简化了我的问题
C面
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;
}
我可以继续,但只需要仔细阅读那本书。
确实不需要与Spring进一步集成。您可以在@Component
上粘贴@Service
或MyFunkyJNIClass
注释。
我希望这对你有所帮助。