2015-08-12 13 views
6

Sto cercando di restituire un jintArray da C++ a Java, ma l'applicazione sembra bloccarsi nella chiamata JNI. Ho ridotto il problema alla creazione e alla popolazione del jintArray, anche se non ricevo errori. Qualsiasi aiuto è apprezzato.Restituzione di jintArray da JNI

progetto di prova per assicurarsi che tutto funzioni:

include "stdafx.h" 
include "windows.h" 
include <vector> 
include <iostream> 
include <jni.h> 

using namespace std; 

std::vector<jint> childWindows; 

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { 
    childWindows.push_back((jint) hwnd); 
    return TRUE; 
} 

jint* getChildWindows(HWND hWnd) { 
    childWindows.clear(); 
    ::EnumChildWindows(hWnd, EnumChildProc, NULL); 

    int len = static_cast<int>(childWindows.size()); 

    jint values[100]; 
    std::copy(childWindows.begin(), childWindows.end(), values); 


    for (std::vector<jint>::const_iterator i = childWindows.begin(); i != childWindows.end(); ++i) { 
     std::cout << (HWND)*i << ' '; 
    } 
    //env->SetIntArrayRegion(childeren, 0, len, values); 
    return values; 
} 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    getChildWindows((HWND)1377258); 

    std::cout << " | Windows count: " << childWindows.size() << " "; 
    return 0; 
} 

uscita:

000D0550 000B04F2 001C047A 0002055E 00020558 00010564 0007054E 00050570 00060512 000C04E0 | contano di Windows: 10 Codice

Java:

System.out.println("Get child windows"); 
    System.out.println("Main handle: " + getHandle()); 
    final int[] handles = getChildWindows(); 
    System.out.println("Done getting childs"); 

Java uscita:

partire finestre figlio prova

Scarica Windows bambino

maniglia principale: 525.978

codice JNI:

JNIEXPORT jintArray JNICALL Java_main_getChildWindows(JNIEnv *env, jclass c) { 
    childWindows.clear(); 
    ::EnumChildWindows(hWnd, EnumChildProc, NULL); 

    int len = static_cast<int>(childWindows.size()); 
    jintArray childeren = env->NewIntArray(len); 

    jint values[100]; 
    std::copy(childWindows.begin(), childWindows.end(), values); 

    env->SetIntArrayRegion(childeren, (jsize)0, (jsize)len, values); 
    //env->ReleaseIntArrayElements(childeren, values, 0); 
    return childeren; 
} 
+0

Hai considerato di aggiungere lo stesso tipo di traccia al metodo JNI che hai nel primo bit del codice C? – EJP

+0

prova a chiamare getChildWindows() in una discussione separata – user2543253

risposta

1

Lei non è il controllo per gli errori dopo la vostra JNI chiama. Ciò può portare a una situazione in cui il codice si arresta in modo anomalo non nel punto in cui si è verificato l'errore ma nel punto successivo in cui si chiama la JVM. Non si avranno "errori" in alcun senso amichevole quando ciò accade. La tua possibilità di ottenerli è controllare i valori di ritorno e interrogare la JVM per le eccezioni in sospeso. (Vedi sotto).

Nel tuo caso, per esempio, se

jintArray childeren = env->NewIntArray(len) 

genera un'eccezione (in Java nella JVM), il codice continuerà passato che riga nel codice nativo, ma la JVM manterrà ancora quell'eccezione. La prossima volta che chiami nella JVM, che è la linea che hai identificato dove hai impostato i valori dell'array, il codice si bloccherà. È necessario cancellare l'eccezione in modo esplicito.

In ogni caso, è necessario controllare i valori di restituzione e verificare le eccezioni. (Vedi i documenti JNI per ExceptionOccurred e ExceptionClear.) Scommetto che per qualche motivo non sei riuscito a ottenere un array allocato. Esattamente perché ciò accadrebbe non mi è chiaro dal tuo codice, ma questo ti darà un punto concreto per iniziare, cioè se hai un'eccezione o se hai un riferimento null che ti darà informazioni su cosa è andato storto. Inoltre, cambierà potenzialmente la tua ricerca nel punto in cui si verifica il problema.

Buona fortuna!