2012-04-24 7 views
9

Mam złożoną strukturę w kodzie C w mojej aplikacji na Androida i chciałbym go użyć po stronie Java. Zrobiłem kilka badań z google i in stackoverflow, więc stworzyłem klasę języka Java z mojego C strucutre, ale teraz, jak uzyskać ją w Javie.Jak przekazać złożoną strukturę między C i Javą z JNI na Androida NDK

Znalazłem te informacje, o co wskaźnik w klasie i wykorzystać to na stronie C:

Get the field ID : (*env)->GetFieldID(...) 
Get the pointer : (*env)->GetLongField(...) 
Set the pointer : (*env)->SetLongField(...) 

Ale ja nie rozumiem, jak to naprawdę działa ...

Powyżej możesz znaleźć to, co do tej pory zrobiłem ... nie tak bardzo! Po stronie C:

ComplexStructure Java_com_main_MainActivity_listenUDP(JNIEnv* env, jclass clazz) 
{ 
    int i,taille; 
    ComplexStructure myStruct;  
    taille = -1;  
    taille = recvfrom(socket, &myStruct, sizeof(ComplexStructure), 0, &rcvAddr, &sizeOfSock); 
    if(taille != -1) 
    { 
     return myStruct; 
    } 
    return NULL; 
} 

A od strony Java:

public void getFromUDP() { 

    ComplexClass myClass = new ComplexClass(); 
    myClass = listenUDP();    
} 

@Override 
public void run() { 
    initUDP(); 
    getFromUDP(); 
} 


public static native ComplexClass listenUDP(); 
public static native void initUDP(); 
public static native void closeUDP(); 

/** Load jni .so on initialization */ 
static { 
    System.loadLibrary("native-interface"); 
} 

EDIT: Chciałbym dodać, że moja konstrukcja jest bardzo złożona tak:

typedef struct{ 
    TYPE_A myStructA; 
    TYPE_B myStructB; 
    TYPE_C myStructC; 
    TYPE_D myStructD; 
}ComplexStructure; 

typedef struct{ 
    float rad; 
    int size; 
    bool isEmpty; 
}TYPE_A; 

typedef struct{ 
    float rad; 
    bool isEmpty; 
    float color; 
    int temp; 
}TYPE_B; 

typedef struct{ 
    int temp; 
    float rain; 
    bool isEmpty; 
}TYPE_C; 

typedef struct{ 
    float rad; 
    int idPerson; 
    bool isOnTime; 
}TYPE_D; 

Nawet więcej złożony, po prostu przykład, aby pokazać, jak to jest!

Odpowiedz

8

Nie można przekazywać surowych struktur C do Javy i oczekiwać, że traktuje te struktury jako klasy. Musisz utworzyć klasę dla swojej struktury. Widzę, że już to zrobiłeś, więc jedyną rzeczą, którą musisz zrobić, to przekonwertować tę strukturę na instancję klasy.

Kod na stronie Java:

public static native ComplexClass listenUDP(); 

przełoży się:

JNIEXPORT jobject JNICALL Java_com_main_MainActivity_listenUDP(JNIEnv *env, jclass); 

W tym kodzie C, trzeba załadować ComplexClass użyciu funkcji env->FindClass();. Następnie, aby utworzyć nową instancję tej klasy (upraszcza to sprawę, jeśli masz konstruktor z zerowym parametrem), musisz załadować sygnaturę metody konstruktora i "wywołać" ją w metodzie env->NewObject(). Pełny kod:

jclass complexClass = env->FindClass("/com/main/ComplexClass"); 
jmethod constructor = env->GetMethodId(complexClass, "<init>", "()com/main/ComplexClass"); //The name of constructor method is "<init>" 
jobject instance = env->NewObject(complexClass, constructor); 

Następnie należy ustawić pola tej klasy, używając env->setXXXField();. Jeśli masz więcej obiektów jako pól i chcesz je utworzyć, powtórz powyższy proces dla innego obiektu.

Wygląda to bardzo skomplikowanie, ale jest to cena za używanie natywnego C w zarządzanym kodzie Java.

+0

OK, dziękuję bardzo za odpowiedź, jest to bardzo pomocne. Jak sam mówisz, jest to bardzo skomplikowane, pomyślałem, że można skopiować strukturę do klasy, ale to nie jest ... Ponieważ moja struktura ma wiele obiektów/pól, więc jeśli muszę ręcznie dodać wszystkie parametry, to minie dni na nim. A więc czy najprościej jest odbierać bezpośrednio w Javie pakiet UDP z mojej aplikacji C? Dziękuję bardzo @Jakub Zaverka – Bibu

+1

@Martin Spójrz na Datagramy: http://docs.oracle.com/javase/tutorial/networking/datagrams/index.html –

+0

Tak, wiem, jak korzystać z DatagramSocket et DatagramPacket, ale Nie wiem jak odzyskać moje dane :) dla String jest to dość proste, ale dla struktury ... – Bibu