Ich habe eine native Methode mit benutzerdefinierten Datentypen (Struktur) als Parameter, wie rufe ich diese Methode von Java mit JNI?
Antworten
Zu viele Anzeigen?Wenn Sie eine Methode wie diese haben:
int cFunction(mydatatype data) ...
Sie können ihn nicht direkt aufrufen. Sie benötigen eine Schicht von JNI, um sie zusammenzukleben.
Eine JNI-Funktion ist also etwas, das aus Ihrem Code generiert wird:
class JavaTest {
public native int jMethod(int a);
}
Laufen javah
auf diese Klasse anwenden, erhalten Sie eine Header-Datei wie diese:
JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a);
Die Implementierung dieser Methode zum Aufruf von cFunction(mydatatype)
:
JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a) {
mydatatype data;
data.count = a;
return (jint) cFunction(data);
}
Es gibt eine Möglichkeit, die Felder eines Java-Objekts zu lesen:
jint _JMETHODNAME(MyClass,myMethod) (JNIEnv *env, jclass jcMyClass, jobject joMyObject)
{
//Get the class
jcMyObjectClass = env->FindClass("test/native/MyObject");
if (jtException = env->ExceptionOccurred())
{
//Error management
}
if (jcMyObjectClass == NULL)
{
//Error management
}
//Check if the class matchs the object
jboolean jbFlag = env->IsInstanceOf(joMyObject,jcMyObjectClass);
if (jtException = env->ExceptionOccurred())
{
//Error management
}
if (jbFlag == JNI_FALSE)
{
//Error management
}
//Get a field
jfieldID jfIdentField = env->GetFieldID(jcMyObjectClass,"fieldName","Ljava/lang/String;");
if (jtException = env->ExceptionOccurred())
{
//Error management
}
if (jfIdentField == NULL)
{
//Error management
}
//Read a field
jstring jsMyString = (jstring)env->GetObjectField(joMyObject,jfIdentField);
if (jtException = env->ExceptionOccurred())
{
//Error management
}
if (jsMyString == NULL)
{
//Error management
}
//Convert to C++ format
LPCTSTR strMyString = (LPTSTR)env->_tGetString(jsMyString, NULL);
jsize myStringLen = env->_tGetStringLength(jsMyString);
if (strMyString == NULL)
{
//Error management
}
}
Sie können also ein Java-Objekt als Parameter verwenden und es in eine C-Struktur umwandeln, wenn Sie wollen.
Vielleicht hilft Ihnen das weiter.
Bei einem selbstreferenzierten Objekt können Sie alle diese Objekte auf diese Weise durchgehen:
//Get a field
jfieldID jfIdentField = env->GetFieldID(jcMyObjectClass,"selfReference","test/native/MyObject");
if (jtException = env->ExceptionOccurred())
{
//Error management
}
if (jfIdentField == NULL)
{
//Error management
}
//Read a field
jobject joNextMyObject = (jstring)env->GetObjectField(joMyObject,jfIdentField);
if (jtException = env->ExceptionOccurred())
{
//Error management
}
while (joNextMyObject != NULL)
{
//Process object
//Read a field
joNextMyObject = (jstring)env->GetObjectField(joNextMyObject,jfIdentField);
if (jtException = env->ExceptionOccurred())
{
//Error management
}
}