2009-07-31 13 views
3

J'appelle une DLL en lui passant un objet de fonction de rappel. Une des fonctions est l'impression simple. J'ai alors, une boucle de 100 itérations, juste l'impression de l'index et quelques tirages après la boucle.JNA - Violation d'accès, terminaisons JVM


Voici le code C

extern "C" int Start(void* callback(CString)) 
{ 
    for(int j=0; j<100; j++) 
    callback(AConvertToString(j)); 

    callback("in Start called from Java"); 
    callback("another line"); 
} 

Voici le code Java

public interface MyDll extends Library{ 
    MyDll INSTANCE = (MyDll) Native.loadLibrary("MyDll",MyDll.class); 
    public interface MyCallback extends StdCallCallback { 
      public boolean callback(String msg); 
    } 
    public int Start(MyCallback callback); 
    } 

//in main: 
... 
    MyDll myDll = (MyDll)MyDll.INSTANCE; 
    myDll.Start(new MyDll.MyCallback() { 
     public boolean callback(String msg) { 
     System.out.println(msg); 
      return true;   
     } 
}); 

La sortie est un nombre 0..41 (YES !!! 41 pas 99) puis "dans Start appelé de Java" suivi d'un horrible accident:

# 
# An unexpected error has been detected by Java Runtime Environment: 
# 
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x7c809823, pid=468, tid=2636 
# 
# Java VM: Java HotSpot(TM) Client VM (10.0-b23 mixed mode, sharing windows-x86) 
# Problematic frame: 
# C [kernel32.dll+0x9823] 

J'ai lu beaucoup (ici aussi) mais je ne trouve pas le problème. Je cours JRE de Java6. J'ai 1,5 Go de mémoire sur ma machine. La DLL n'est utilisée par aucun autre processus (aucun problème de concurrence).

Merci, Azriel

+0

Peut-être que la convention d'appel de votre DLL n'est pas StdCall? – akarnokd

+0

Au lieu de préfixer avec répondu, vous devez «accepter» la réponse (cliquez sur la coche). –

Répondre

4

Essayez d'écrire votre MyCallback comme com.sun.jna.Callback plutôt comme un com.sun.jna.win32.StdCallLibrary.StdCallCallback:

public interface MyDll extends Library{ 
    MyDll INSTANCE = (MyDll) Native.loadLibrary("MyDll",MyDll.class); 
    public interface MyCallback extends Callback { 
      public boolean callback(String msg); 
    } 
    public int Start(MyCallback callback); 
    } 

Cordialement, Emmanuel Girard

+0

Merci, cela a fait l'affaire. Une chose si mineure ... – aabramovich

2

Dans mon cas, le développement d'une application de télécommunications qui utilise une DLL win32 c'était le cas contraire.

En utilisant com.sun.jna.Library et com.sun.jna.Callback, il écrasait toujours la machine virtuelle lors du retour de l'appel de rappel. Après la modification de com.sun.jna.win32.StdCallLibrary et de com.sun.jna.win32.StdCallLibrary.StdCallCallback, le problème a été résolu.