Zor*_*Hut 11 iphone uiapplication nsrunloop
我正试图将游戏库移植到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();
}
Run Code Online (Sandbox Code Playgroud)
iPhone使这很困难,因为它要求你调用一个永不返回的UIApplicationMain函数.在library_init();之后我根本无法回到用户代码.
我不相信它是必要的 - 有NSRunLoop可以用来处理这些事件.然而,我不知道UIApplicationMain是否做了其他重要的事情.(请注意,我没有计划使用.nib文件,这是我发现UIApplicationMain唯一的另一件事.)
我有三个我能想到的真实想法,但它们都是一项重大的实施工作,所以我想知道是否有人有这方面的经验,然后我会花一天时间尝试注定的想法.
建议?
看起来我在这里回答了我自己的问题!在我能够在真实硬件上进行测试并将其放入应用商店之前,我不接受我的回答.也就是说,我会在这里保留我最新的信息,包括哪些选项不起作用.
想法#1:事实证明每个NSRunLoop都是特定于线程的.如果我在一个单独的线程中创建一个UIApplicationMain,它就不会收到任何消息.作为一个副作用,这使得无法确定它何时完成初始化,所以如果它有任何非线程安全,它就行不通.我或许可以通过线程向它发送一条消息,以确定它何时完成初始化,但是现在我称之为死路一条.
想法#2:UIApplicationMain做了许多微妙的事情.我不确定它的限制,但如果不涉及UIApplicationMain,我无法做任何事情.想法#2就出来了.
想法#3:接收操作系统信号很重要 - 您需要知道是否有电话呼叫覆盖,或者您是否即将退出.最重要的是,为了正确启动应用程序,一些设置消息似乎至关重要.我无法找到任何方法来保持消息不被UIApplicationMain内部发送.我想出的唯一选择是NSRunLoop和CFRunLoop.两个人都没有工作 - 这些消息没有像我想的那样进来.我可能没有正确使用这些,但无论如何,Idea#3已经出局了.
全新的疯狂想法#4:可以使用setjmp/longjmp在C/C++中伪造协同程序.诀窍是首先将堆栈指针设置为一些不会破坏任何重要的值,然后启动第二个例程,然后来回跳转,假装你有两个堆栈.如果你的"第二个协同程序"决定从它的主要功能返回,事情会变得有点混乱,但幸运的是,UIApplicationMain永远不会返回,所以这不是问题.
我不知道是否有办法在真实硬件上显式设置堆栈指针,比如说,我是动态分配的一大块数据.幸运的是,没关系.iPhone默认拥有1MB的堆栈,这很容易适合几个协同程序.
我目前正在做的是使用alloca()将堆栈指针向前推768千字节,然后产生UIApplicationMain,然后使用setjmp/longjmp在我的"UI例程"和我的"主例程"之间来回反弹.到目前为止,这是有效的.
注意事项:
不可能知道"UI例程"何时没有要处理的消息,并且当它没有要处理的消息时,它将无限期地阻塞,直到不再是这种情况.我通过制作一个每0.1毫秒触发一次的定时器来解决这个问题.每次定时器触发时,我都会退出我的"主程序",进行单个游戏循环,然后返回"UI例程"进行另一个计时器滴答.阅读文档表明它不会无限期地堆叠"定时器调用".我似乎得到了适当的"终止"消息,虽然我还没有设法彻底测试它,我还没有测试任何其他重要的消息.(幸运的是,总共只有四条消息,其中一条与设置相关.)
大多数现代操作系统不会立即分配整个堆栈.iPhone可能就是其中之一.我不知道的是,撞到一个meg前锋的堆栈指针3/4是否会分配"在它后面"的所有东西,可以这么说.如果是这样的话,我可能会有效地浪费3/4的内存,这在iPhone上很重要.这可以通过将指针向前撞击一个较小的数量来处理,但这实际上是在追求堆栈大小的灾难 - 它有效地限制了你的堆栈,无论你向前碰撞指针,你都必须事先弄明白.堆栈中的一些标记数据,加上良好的监控和堆栈大小问题的日志记录系统,可能可以解决这个问题,但这是一个非常重要的问题.(或者,如果我能弄清楚如何直接在本机硬件上使用堆栈指针,我可以将malloc()/ new []几千字节,指向堆栈指针,并将其用作我的新堆栈.我将不得不弄清楚它需要多少空间,但我怀疑它会有多大,考虑到它没有做太多.)
目前尚未在实际硬件上进行测试(给它一两个星期,我有另一个项目要先完成.)
当我尝试提交到应用程序商店时,我不知道Apple是否会弄明白我正在做什么并在其上拍一个巨大的REJECTED贴纸.我们可以说,这略微超出了他们对API的意图.手指交叉.
我会保持这篇文章的最新更新,并且一旦我确认它已经确认可行,我们会正式接受它.
延迟更新:我被其他各种事情分心了.从那时起,我做了一些改变,使我对Apple开发的兴趣大增.我目前的做法,未发现任何迹象没有工作,但我真的没有动力继续充实它.抱歉! 如果我改变主意,我会进一步更新,但Outlook不太好.
目标是采用 main() 函数并让它在 iPhone 上不加修改地工作吗?
看起来你不可能完全让库的用户不去思考 iPhone 平台——他们将不得不使用 XCode 来进行代码签名之类的事情。
鉴于此,告诉用户他们必须将 main() 函数分成几个部分,您可以从 applicationDidFinishLaunching 和适当的计时器中调用这些部分,这似乎不会给任何人带来太多不便。
| 归档时间: |
|
| 查看次数: |
2865 次 |
| 最近记录: |