2009-10-31 2 views
1

J'ai essayé de coder une application de capture d'écran simple en utilisant rococoa (java à osx cacao api library), et j'ai réussi à aller aussi loin que de prendre la capture d'écran, puis l'enregistrer dans un fichier. Malheureusement, une fois de temps en temps, l'application échoue avec une erreur 'Invalid memory access of location ...'. Je suppose que cela est dû au fait que quelque chose a été collecté, parce que je n'arrive pas à garder une référence en vie. La ligne qui provoque le plantage est: int [] data = pointer.getIntArray (0, bytesPerPlane/4);Accès mémoire non valide de l'emplacement avec Rococoa

Je n'ai vraiment rien codé avec l'Objective C, et je commence juste avec rococoa, donc je me trouve juste confus avec ça. J'ai copié le code approprié ci-dessous, et apprécierais vraiment n'importe quelle aide avec ceci!


public interface QuartzLibrary extends Library { 

    QuartzLibrary INSTANCE = (QuartzLibrary) Native.loadLibrary("Quartz", QuartzLibrary.class); 

    class CGPoint extends Structure { 
     public double x; 
     public double y; 
    } 

    class CGSize extends Structure { 
     public double width; 
     public double height; 
    } 

    class CGRect extends Structure implements Structure.ByValue { 
     public static class CGRectByValue extends CGRect { } 

     public CGPoint origin; 
     public CGSize size; 
    } 

    int kCGWindowListOptionIncludingWindow = (1 << 3); 
    int kCGWindowImageBoundsIgnoreFraming = (1 << 0); 

    ID CGWindowListCreateImage(CGRect screenBounds, int windowOption, int windowId, int imageOption); 
} 

public interface NSBitmapImageRep extends NSObject { 

    public static final _Class CLASS = Rococoa.createClass("NSBitmapImageRep", _Class.class); 

    public interface _Class extends NSClass { 
     NSBitmapImageRep alloc(); 
    } 

    NSBitmapImageRep initWithCGImage(ID imageRef); 
    com.sun.jna.Pointer bitmapData(); 
    NSSize size(); 
} 

public class Screenshot { 

    public static void getScreenshot(int windowId) throws IOException { 
     QuartzLibrary.CGRect bounds = new QuartzLibrary.CGRect.CGRectByValue(); 
     bounds.origin = new QuartzLibrary.CGPoint(); 
     bounds.origin.x = 0; 
     bounds.origin.y = 0; 
     bounds.size = new QuartzLibrary.CGSize(); 
     bounds.size.width = 0; 
     bounds.size.height = 0; 
     ID imageRef = QuartzLibrary.INSTANCE.CGWindowListCreateImage(bounds, QuartzLibrary.kCGWindowListOptionIncludingWindow, windowId, QuartzLibrary.kCGWindowImageBoundsIgnoreFraming); 

     NSBitmapImageRep imageRep = NSBitmapImageRep.CLASS.alloc(); 
     imageRep = imageRep.initWithCGImage(imageRef); 
     NSSize size = imageRep.size(); 
     com.sun.jna.Pointer pointer = imageRep.bitmapData(); 

     int width = size.width.intValue(); 
     int height = size.height.intValue(); 

     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 
     // The crash always happens when calling 'getIntArray' in the next line. 
     int[] data = pointer.getIntArray(0, bytesPerPlane/4); 
     int idx = 0; 
     for(int y = 0; y < height; y++) 
      for(int x = 0; x < width; x++) 
       image.setRGB(x, y, data[idx++]); 

     ImageIO.write(image, "png", new File("foo.png")); 
    } 
} 

Répondre

2

a trouvé le problème.

La dernière utilisation de 'imageRep' est sur la ligne "com.sun.jna.Pointer pointer = imageRep.bitmapData();". Après cela, imageRep est un jeu équitable pour le garbage collector Java. Et si cela arrive en avant que nous ayons fini d'utiliser 'pointer', le tampon de sauvegarde vers lequel il pointe peut/va obtenir libéré, provoquant de mauvaises choses. Pour résoudre ce problème, l'ajout d'un ensemble supplémentaire de conservation/libération pour imageRep effectue le travail, ou en ajoutant une référence à la fin de la méthode.

0

Peut-être lié, peut-être pas: NSBitmapImageRep descend de NSImageRep, pas directement de NSObject.

Questions connexes