问题描述
我们使用 qt(https://www.qt.io) 来开发应用程序。
Qt 通过传递 QWidget::winId() 来共享小部件(QWidget),接收方调用 QWindow::fromID() 来取回小部件。 像下面的代码:
Code A:
WId winId = this->winId(); //QWidget::winId()
SendToB(winId)
Code B:
WId winId = ReceiveFromA()
QWindow *window = QWindow::fromWinId( winId );
QWidget* widgetofA = QWidget::createWindowContainer(window,this,Qt::Widget );
然后 QWidget::winId() 在 Windows 操作系统上获取 HWND,这是有效的,因为 Windows 上的 HWND 由操作系统全局管理。所以“代码B”可以从“代码A”中获取HWND/QWidget并渲染进去。
我们的qt app是按照“进程A获取进程B的widget并管理它”的设计构建的。
但在 Mac OS X 上,QWidget::winId() 是通过将 NSView* 的地址作为 QWidget::winId() 传递,并使用 (NSView*)winID 将其转换回 NSView* 来实现的。
这并不优雅,但它确实在相同的过程中起作用。
当然,当“代码A”和“代码B”属于两个主/子进程时。这不起作用。
当我们尝试通过从其他进程的地址转换来访问 NSView* 时,我们的应用程序会崩溃。
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00007fea7e8d9770
Exception Note: EXC_CORPSE_NOTIFY
我尝试使用 [NSWindow windowNumber] 和 [[NSApplication sharedApplication] windowWithWindowNumber:windowNumber] 如下:
- (void)applicationDidFinishLaunching()
{
NSWindow* mainWindow = [[NSApplication sharedApplication] windows] [0]; //the NSWindow* to be shared.
mainWindow.sharingType = NSWindowSharingReadWrite; //to allow other process access its content.
if (fork() > 0 ) //create a sub process
{
// the original/main process
NSInteger windowNumber = mainWindow.windowNumber;
SendToSubProcess(windowNumber);
}
else
{
NSInteger windowNumber = ReceiveFromMainProcess();
NSWindow * receivedWindow = [[NSApplication sharedApplication] windowWithWindowNumber:windowNumber];
/*
We Could get the correct NSWindow* here (Only if sharingType has been set to NSWindowSharingReadWrite)
But we Could not add sub-ui to receivedWindow, otherwise we'll get following error:
The process has forked and you cannot use this CoreFoundation functionality safely.
You MUST exec(). Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_
COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.
so we have to use execv() here
*/
char execPath[PATH_MAX];
uint32_t execPathSize = sizeof(execPath);
(void) _NSGetExecutablePath(execPath,&execPathSize);
const char * args[] = {execPath,"in_subprocess",windowNumber.c_str(),nullptr};
(void) execv(execPath,(char * const *) args);
kill(getpid(),SIGKILL);
}
}
int main(int argc,const char * argv[]) {
@autoreleasepool {
if (argc >= 3)
{
if (strcmp(argv[1],"in_subprocess") == 0)
{
//launched by execv() of sub process
intptr_t windowNumber = atoll(argv[2]);
NSWindow * mainWindow = [[NSApplication sharedApplication] windowWithWindowNumber:windowNumber];
//mainWindow is nil because it's another NSApplication
//How Could we shared it here?
return 0;
}
}
}
return NSApplicationMain(argc,argv);
}
我也试过CGWindowXXX函数,还没有结果。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)