gpt4 book ai didi

iphone - 如何从 iPhone 应用程序中删除 UIApplicationMain?

转载 作者:行者123 更新时间:2023-12-03 18:27:29 26 4
gpt4 key购买 nike

我正在尝试将游戏库移植到 iPhone。与 SDL 不同,这个库不会完全控制您的 main() 函数,它通过您自己代码中的快速返回函数进行通信。因此,例如,明显的伪代码:

int main() {
library_init();
// game init code here
while(we_have_not_quit_the_game) {
library_message_loop();
library_init_render();
// render stuff
library_end_render();
// update game state
}
library_shutdown();
}

iPhone 使这变得困难,因为它要求您调用一个永不返回的 UIApplicationMain 函数。在 library_init(); 之后,我根本无法回到用户代码。

我不相信这是必要的 - 有 NSRunLoop 据说可以用来处理事件。但是,我不知道 UIApplicationMain 是否还有其他重要的事情。 (请注意,我没有计划使用 .nib 文件,这是我发现 UIApplicationMain 所做的唯一其他事情。)

我有我能想到的三个真正的想法,但它们都是一项重大的实现工作,所以我想知道在我花一天时间尝试注定的想法之前是否有人有这方面的经验。
  • 在 Init 中,产生一个新线程,在该线程中运行 UIApplicationMain。要么跨线程传递所有事件(呃),要么只是让 UIApplicationMain 线程休眠并在主线程中使用 CFRunLoop。但是,我听说 UIApplicationMain 不喜欢在不同的线程中运行。
  • 完全忽略 UIApplicationMain,只需使用 NSRunLoop。我会错过重要的 iPhone 设置吗?谁知道!
  • 在设置后用 longjmp() 做一些可怕的事情来跳出 UIApplicationMain 代码,祈祷它在拆卸过程中不会做任何重要的事情。

  • 建议?

    最佳答案

    看起来我在这里回答我自己的问题!我不接受我的答案,直到我能够在真实的硬件上测试它并将其放入应用程序商店。也就是说,我会在这里保留我的最新信息,包括哪些选项不起作用。

    想法#1 :事实证明,每个 NSRunLoop 都是特定于线程的。如果我在单独的线程中创建 UIApplicationMain,它不会收到任何消息。作为一个副作用,这使得无法确定它何时完成初始化,所以如果它有任何非线程安全的东西,它就不会工作。我也许可以跨线程向它发送一条消息,以确定它何时完成初始化,但现在我称之为死胡同。

    想法#2 : UIApplicationMain 做了很多微妙的事情。我不确定它的限制是什么,但是如果不涉及 UIApplicationMain,我就无法进行任何工作。想法#2 是正确的。

    想法#3 :接收操作系统信号很重要 - 您需要知道是否有电话覆盖,或者您是否即将退出。最重要的是,一些设置消息对于正确启动应用程序似乎至关重要。如果不在 UIApplicationMain 中,我无法找到任何方法来保持消息的发送。我想出的唯一选项是 NSRunLoop 和 CFRunLoop。没有一个工作 - 消息没有像我想要的那样进入。我可能没有正确使用这些,但无论如何,想法 #3 已经过时了。

    全新的疯狂想法#4 :可以在 C/C++ 中使用 setjmp/longjmp 来伪造协程。诀窍是首先将堆栈指针设置为某个不会破坏任何重要内容的值,然后开始您的第二个例程,然后来回跳转,假装您有两个堆栈。如果你的“第二个协程”决定从它的主函数返回,事情会变得有点困惑,但幸运的是, UIApplicationMain 永远不会返回,所以这不是问题。

    我不知道是否有办法在真实硬件上显式设置堆栈指针,例如,设置为我动态分配的数据块。幸运的是,没关系。 iPhone 默认有一个 1MB 的堆栈,这足以容纳几个协程。

    我目前正在做的是使用 alloca() 将堆栈指针向前推送 768 KB,然后生成 UIApplicationMain,然后使用 setjmp/longjmp 在我的“UI 例程”和“主例程”之间来回弹跳。到目前为止,这是有效的。

    注意事项:

  • 不可能知道“UI 例程”何时没有消息要处理,而当它没有消息要处理时,它将无限期地阻塞,直到不再是这种情况。我正在通过制作一个每 0.1 毫秒触发一次的计时器来解决这个问题。每次计时器触发时,我都会退出我的“主程序”,执行一个游戏循环,然后返回“UI 程序”进行另一个计时器滴答。阅读文档表明它不会无限期地堆积“计时器调用”。我似乎确实适本地收到了“终止”消息,尽管我还没有设法对其进行彻底的测试,而且我还没有测试过任何其他重要的消息。 (幸运的是,总共只有四条消息,其中一条与设置相关。)
  • 大多数现代操作系统不会一次分配整个堆栈。 iPhone 可能就是其中之一。我不知道的是,将堆栈指针向前撞到 meg 的 3/4 是否会分配“后面”的所有内容,可以这么说。如果是这样,我可能会有效地浪费 3/4 兆内存,这在 iPhone 上非常重要。这可以通过将指针向前移动较小的量来处理,但这确实会导致堆栈大小的灾难 - 它有效地限制了您的堆栈,无论您将指针向前移动多远,您都必须提前弄清楚这一点。堆栈中的一些哨兵数据,加上良好的监控和堆栈大小问题的日志记录系统,可能可以解决这个问题,但这是一个重要的问题。 (或者,如果我能弄清楚如何直接在 native 硬件上处理堆栈指针,我只需 malloc()/new[] 几千字节,将堆栈指针指向它,并将其用作我的新堆栈。我必须弄清楚它需要多少空间,但我怀疑它需要多少空间,因为它并没有做太多。)
  • 目前尚未在实际硬件上进行测试(给它一两个星期,我要先完成另一个项目。)
  • 我不知道当我尝试向应用商店提交时,Apple 是否会弄清楚我在做什么并在上面贴上一个巨大的 REJECTED 贴纸。容我们说,这稍微超出了他们对 API 的意图。手指交叉。

  • 我会不断更新这篇文章,并在我确认它有效后正式接受它。

    后期更新:我被其他各种事情分散了注意力。从那以后,我发生了一些变化,使我对 Apple 开发的兴趣大大降低。我目前的方法没有显示出不起作用的迹象,但我真的没有动力继续充实它。对不起!如果我改变主意,我会进一步更新,但 Outlook 不太好。

    关于iphone - 如何从 iPhone 应用程序中删除 UIApplicationMain?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2187684/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com