Как я могу удалить UIApplicationMain из приложения для iPhone?

Я пытаюсь портировать игровую библиотеку на iPhone. В отличие от SDL, эта библиотека не берет на себя полное управление Вашего основного () функция, ею общаются с через быстро возвращающиеся функции из Вашего собственного кода. Так, например, очевидный псевдокод:

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 после установки, молиться, чтобы это не делало ничего важного во время разрушения.

Предложения?

11
задан ZorbaTHut 6 February 2010 в 05:45
поделиться

4 ответа

- это цель, чтобы принять эту главную () функцию и у него работают немодифицированные на iPhone?

Казалось бы, есть никаких возможностей, вы не собираетесь полностью изолировать пользователями библиотеки, думая о платформе iPhone - Они придется иметь дело с XCode для подписания кода и такого рода вещей.

Учитывая, что, рассказывая пользователям, которые они должны сломать свою главную () функцию на несколько штук, которые вы можете позвонить с ApplicationDIDFINISHLAUCHING, и из подходящего таймера кажется, что это неудобство.

0
ответ дан 3 December 2019 в 11:20
поделиться

Почему бы не запустить игровой цикл из UIApplication? (Да, вы не можете использовать его в main () , но это не имеет значения.) Некоторые сообщения делегатов являются хорошими кандидатами.

0
ответ дан 3 December 2019 в 11:20
поделиться

Похоже, я сам отвечаю на свой вопрос! Я не приму свой ответ до тех пор, пока не смогу протестировать его на реальном оборудовании и доставить его в магазин приложений. Тем не менее, я буду хранить здесь свою самую актуальную информацию, включая информацию о том, какие опции не работали.

Идея #1 : Оказалось, что каждый NSRunLoop зависит от потока. Если я создаю UIApplicationMain в отдельном потоке, он не получает никаких сообщений. Побочным эффектом является то, что невозможно определить, когда инициализация закончена, так что если есть что-то нечто неточное, что он делает, то это просто не будет работать. Возможно, я смогу отправить ему сообщение через потоки, чтобы выяснить, когда инициализация закончена, но пока что я называю это тупиком.

Идея #2 : UIApplicationMain делает много тонких вещей. Я не уверен, на что это ограничено, но я не смог заставить что-либо работать без участия UIApplicationMain. Идея №2 прямо сейчас.

Идея #3 : Прием сигналов ОС важен - вам нужно знать, есть ли накладка на телефонный звонок, или вы собираетесь выходить. Вдобавок ко всему, некоторые сообщения о настройках кажутся жизненно важными для правильного запуска приложения. Я не смог найти ни одного способа сохранить отправку сообщений, не находясь внутри UIApplicationMain. Единственными вариантами, которые я придумал, были NSRunLoop и CFRunLoop. Ни один из них не работал - сообщения приходили не так, как я хотел. Может быть, я и не пользуюсь этим правом, но в любом случае, Idea #3 вышла.

Совершенно новая сумасшедшая Идея №4: Можно использовать setjmp/долгое время, чтобы подделать корутины в C/C++. Фокус в том, чтобы сначала установить указатель стека на некоторое значение, которое не будет засорять ничего важного, а затем начать вторую рутину, затем прыгать туда-сюда, притворяясь, что у вас два стека. Все становится немного запутанным, если ваш "второй корутин" решает вернуться из своей основной функции, но, к счастью, UIApplicationMain никогда не возвращается, так что это не проблема.

Я не знаю, есть ли способ установить указатель стека явно на реальное аппаратное обеспечение, скажем, на кусок данных, который я выделял на лету. К счастью, это не имеет значения. По умолчанию iPhone имеет 1МБ стека, что достаточно просто, чтобы поместить в него несколько корутинов.

В настоящее время я использую аллока() для проталкивания указателя стека вперед на 768 килобайт, затем порождаю UIApplicationMain, затем использую setjmp/долгое время для отскока назад и вперед между моей "рутиной пользовательского интерфейса" и моей "основной рутиной". Пока это работает.

Caveats:

  • Невозможно узнать, когда "рутина пользовательского интерфейса" не имеет сообщений для обработки, а когда она не имеет сообщений для обработки, она будет просто блокировать на неопределенное время, пока этого больше не произойдет. Я решаю эту проблему, делая таймер, который срабатывает каждые 0.1 миллисекунды. Каждый раз, когда таймер срабатывает, я выпадаю на мой "основной рутины", сделать один цикл игры, а затем вернуться в "UI рутины" для другого тика таймера. Читая документацию показывает, что он не будет складывать "звонки таймера" бесконечно. Похоже, что я действительно получаю сообщение "termination" соответственно, хотя я еще не успел его тщательно протестировать, и я не протестировал никаких других важных сообщений. (К счастью, всего четыре сообщения, и одно из них связано с установкой)

  • Большинство современных операционных систем не выделяют весь стек сразу. Вероятно, iPhone - один из них. То, что я не знаю, является ли удар указателя стека 3/4 от мега вперед будет выделять все "за ним", так сказать. Если да, то я могу быть эффективно растрачивать 3 / 4 мега оперативной памяти, которая, на iPhone, является значительным. Это может быть обработано путем натыкания указателя вперед меньшую сумму, но это действительно ухаживания за размер стека катастрофы - это эффективно ограничивает ваш стек, однако далеко вы натыкаться на указатель впереди, и вы должны будете выяснить это заранее. Некоторые дозорные данные в стеке в сочетании с хорошим мониторингом и системой регистрации проблем с размером стека, вероятно, могут решить эту проблему, но это нетривиальная проблема. (В качестве альтернативы, если я смогу разобраться с указателем стека непосредственно на "родном" оборудовании, я могу просто Malloc()/new[] несколько килобайт, направить на него указатель стека и использовать его в качестве своего нового стека. Мне придётся выяснить, сколько места ему нужно, но я сомневаюсь, что это будет много, учитывая, что он не очень много делает.)

  • Это в настоящее время не протестировано на реальном "железе" (дайте ему неделю или две, у меня есть ещё один проект, который я должен закончить первым.)

  • Я понятия не имею, выяснит ли Apple, что я делаю, и наклеит на него гигантскую наклейку REJECTED, когда я пытаюсь отправить её в App Store. Это, скажем так, немного выходит за рамки их намерений в отношении API. Пальцы скрещены.

Я буду держать этот пост в курсе, и официально приму его, как только проверю, что он, знаете ли, работает.

Позднее обновление: я отвлекся на множество других вещей. С тех пор у меня есть несколько изменений, которые делают меня гораздо менее заинтересованным в разработке Apple. Мой нынешний подход не показал никаких признаков не работы, но на самом деле у меня нет мотивации продолжать его наполнять. Извините! Если я когда-нибудь передумаю, я обновлю это дальше, но Outlook не так хорош.

5
ответ дан 3 December 2019 в 11:20
поделиться

Я знаю, что NSApplicationMain () читает Info.plist и выполняет какие-то действия с приложением (например, получает исходный файл пера), поэтому я бы угадайте, что UIApplicationMain () делает то же самое для iPhone (например, получает исходный стиль строки состояния, увеличивает изображение default.png и т. д.). Этот материал больше нигде не отображается, поэтому вызываемые им функции все равно необходимо запускать для запуска приложения без каких-либо побочных эффектов. Вы только ставите на то, чтобы перепроектировать их и скопировать (и надеяться, что все, что они делают, есть в общедоступном SDK).

1
ответ дан 3 December 2019 в 11:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: