3 Stimmen

Wie kann man eine native Methode mit benutzerdefinierten Datentypen als Parameter von Java aus aufrufen?

Ich habe eine native Methode mit benutzerdefinierten Datentypen (Struktur) als Parameter, wie rufe ich diese Methode von Java mit JNI?

2voto

dacwe Punkte 42433

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);
}

2voto

raven1981 Punkte 1375

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
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X