2009-10-31 3 views
1

로코코아 (Java to osx cocoa api library)를 사용하여 간단한 스크린 샷 응용 프로그램을 코딩하려고 시도했지만 실제로 스크린 샷을 찍은 다음 파일. 불행히도, 한동안, 응용 프로그램이 '위치의 잘못된 메모리 액세스 ...'오류로 실패합니다. 나는 이것이 살아있는 참조를 유지하지 못하고 있기 때문에 이것이 가비지 수집되는 무언가에 의한 것이라고 가정하고 있습니다. 충돌을 일으키는 행은 다음과 같습니다. int [] data = pointer.getIntArray (0, bytesPerPlane/4);Rococoa에서 위치의 잘못된 메모리 액세스가 발생했습니다.

나는 정말로 Objective C로 코딩을하지 않았으며 단지 로코코아로 시작 했으므로 혼란 스러울뿐입니다. 나는 아래의 관련 코드를 복사했으며, 이것에 대한 도움을 주시면 감사하겠습니다!


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

답변

2

발견.

'imageRep'의 마지막 사용은 "com.sun.jna.Pointer pointer = imageRep.bitmapData();"행에 있습니다. 그런 다음 imageRep는 Java 가비지 컬렉터의 공정한 게임입니다. 그리고 '포인터'를 사용하기 전에 에 도달하면 포인터가 가리키는 버퍼가/ 이 해제되어 나쁜 일이 발생합니다. 이를 수정하려면 imageRep에 대한 추가 retain/release 세트를 추가하여 작업을 수행하거나 메소드에 대한 참조를 메소드 끝에 추가하십시오.

0

아마도 관련, 가능하지 : NSBitmapImageRep가 NSObject의에서 직접적으로, NSImageRep에서 내려.

관련 문제