2014-02-19 2 views
2

Я хочу сделать снимок экрана из фоновой службы. Он отлично работает под ios6 и ios7, но падает под сеткой ios7.IOMobileFramebufferGetLayerDefaultSurface не работает на сетке ios7

это мой код

{ 

IOMobileFramebufferConnection connect; 
     kern_return_t result; 
     m_screenSurfaceRef = NULL; 

     io_service_t framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleH1CLCD")); 
     if(!framebufferService) 
      framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleM2CLCD")); 
     if(!framebufferService) 
      framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleCLCD")); 

#pragma unused(result) 
     result = IOMobileFramebufferOpen(framebufferService, mach_task_self(), 0, &connect); 

     result = IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &m_screenSurfaceRef); 

} 

при запуске на сетчатке IOMobileFramebufferGetLayerDefaultSurface (подключения, 0, & m_screenSurfaceRef) разбился.

аварии Информация:

нить # 1: TID = 0x1dfe9, 0x000000018ea2c270 IOMobileFramebuffer IOMobileFramebufferGetLayerDefaultSurface + 4, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=1, address=0x5e06dc28) frame #0: 0x000000018ea2c270 IOMobileFramebuffer IOMobileFramebufferGetLayerDefaultSurface + 4

+0

Кажется, разбился на 64bit + сетчатка, а не только сетчатка. Вы видите то же самое? – nevyn

+0

@nevyn спасибо, я строю 32-битное приложение, и он работает хорошо. – joeykika

+0

Это несчастливое, но, возможно, приемлемое обходное решение. Однако ответ, который я дал ниже, намного лучше. Хочешь принять его, пожалуйста? – nevyn

ответ

4

Это 64-битная проблема с обратной инженерии IOMobileFramebuffer.h. Прототип

IOMobileFramebufferReturn IOMobileFramebufferGetLayerDefaultSurface(IOMobileFramebufferConnection connection, int surface, CoreSurfaceBufferRef *ptr); 

... неверен, потому что ЬурейеЕ для IOMobileFramebufferConnection неверен. Если один имеет вид на разборку и частичной декомпиляции IOMobileFramebufferGetLayerDefaultSurface:

IOMobileFramebufferReturn IOMobileFramebufferGetLayerDefaultSurface(Connection *connection, int surface, IOSurfaceRef *ptr) 
{ 
    if(connection) {      // 0x18f95026c: cbz x0, 0x18f95027c 
      long tmp = connection->unk2; // 0x18f950270: ldr x3, [x0, #552] // <== Crash! 
      if(tmp) {      // 0x18f950274: cbz x3, 0x18f95027c 
        goto tmp;    // 0x18f950278: br  x3 
      } 
    } 
    //0x18f95027c: movn w0, #8191, lsl #16 
    //0x18f950280: movk w0, #706 
    //0x18f950284: ret lr 

} 

мы видим, что первый параметр разыменовывается, что означает, что он должен быть указателем размера. В обратном заголовке IOMobileFramebufferConnection является typedef'd для io_connect_t, который является typedef'd для io_object_t, который является mach_port_t, который является __darwin_mach_port_t, который является __darwin_natural_t, который является unsigned int! Int просто имеет размер указателя на 32-битном, но не находится под 64-битным, поэтому мы в итоге просто отправляем первые 32 бита указателя на эту функцию, и это, очевидно, сбой.

Мое решение было просто повторно ЬурейеЕ в пустоту * так:

typedef void *IOMobileFramebufferConnection; 

Полный исправлен заголовок можно найти на https://gist.github.com/nevyn/9486278.

Смежные вопросы