“后台”中的多分段 PalmOS 应用程序/库

发布于 2024-07-06 08:55:16 字数 404 浏览 10 评论 0 原文

我遇到的问题是:当使用 sysAppLaunchCmdNormalLaunch 以外的启动代码运行我的应用程序时,我无法使用默认代码段之外的代码 - 但我可以使用多段共享库,从而避免此问题吗?

一些背景信息:我正在评估将现有移动应用程序移植到 PalmOS 的可能性。 该应用程序的核心部分是,它每隔 10 分钟左右或在接收传入数据时(通过网络/套接字回调)在后台进行一些网络通信。 在此期间,我无法访问全局变量,因此无法访问应用程序中除默认代码段之外的任何代码段。

现在的问题是,通信中涉及的操作(协议、数据处理等)需要大量代码,而这些代码根本不适合一个段。 除了在“后台”运行这么多代码是否有意义的问题之外,明显的问题是:我首先将如何运行它? 因此,问题是,将代码放入共享(多段)库中是否会有帮助。

期待您的见解。

the question I am having is: when running my app with a launch code other than sysAppLaunchCmdNormalLaunch, I can not use code outside the default code segment - but could I use a shared library that is multi-segmented, thus circumventing this problem?

A bit of background information: I am evaluating the possibility of porting an existing mobile application to PalmOS. A core part of this app is that it is doing some network communication in the background every 10 minutes or so, or when it receives incoming data (via a network/socket callback). During this time, I do not have access to globals and hence not to any code segments in my application other than the default one.

The problem now is that the actions involved in the communication (protocol, data handling, etc) require a lot of code that just does not fit into one segment. Apart from the question whether it makes sense to have that much code run in the 'background', the obvious problem is: how would I run it in the first place? Hence the question, whether putting the code in a shared (multi-segment) library would help.

Looking forward to your insights.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

审判长 2024-07-13 08:55:16

我没有使用共享库的经验,但我们的软件遇到过这个问题,并且我们遇到了三种不同的方法来解决这个问题。

最简单的方法可能是在使用 Metrowerks 编译器时启用扩展模式,但我不完全确定这是否有效。 这种特殊模式允许您在从非全局启动调用时访问某些恒定的全局数据。 然而,使用这种方法有很多注意事项。 另外,我还没有确认扩展模式确实允许段间跳转。 Ben Combee 撰写了一份白皮书,详细解释了如何使用扩展模式。 它的标题是“在 Palm OS 上支持扩展模式”。 我在网上找不到它,所以我在我的网站上放置了一个副本: http://www.normsoft.com/tim/technical/Codewarrior_Expanded_Mode.pdf

另一个更复杂的选项是自己加载全局变量并在 A5 中放置指向它们的指针。 为此,您必须修改(或复制)加载全局变量的 Metrowerks 启动代码,然后在收到非全局启动时调用此修改后的代码。 Metrowerks 包含这部分运行时的完整源代码,因此您可以非常轻松地完成此操作,尽管其中一些代码非常晦涩难懂。 我们成功地在 Pocket Tunes 的一个版本中使用了这一技术,以便在从非全局启动代码调用时访问全局变量和无限数量的段。 从启动代码返回时请务必恢复 A5。

最后的选择是将所有(或部分)代码移至 PNOlet 中。 这可能会很痛苦,因为您必须将代码分段为 68K 和 PNO,这很快就会成为维护的噩梦。 我们也成功地使用了这种方法,但是互通代码的维护非常糟糕。 我们最终使用 PEAL 加载器将整个代码移动到 PNOlet,这对于大型代码非常有效,因为它会自动将代码分割成 64KB 块并就地运行 ARM 代码。 然而,这是一项非常巨大的工作,因为 PNOlet 开发在 ARM 上没有得到很好的支持,因此您必须自己提供大量低级支持(例如调用每个 API 函数的 thunk)。

I don't have experience with using shared libraries, but we've had this problem with our software, and we've come across three different ways to solve the problem.

Possibly the easiest is to enable Expanded Mode when using the Metrowerks compiler, but I'm not completely certain that this works. This special mode allows you to access certain constant global data when called from a non-global launch. However, there are a lot of caveats to using this approach. Also, I have not confirmed that Expanded Mode allows inter-segment jumps for sure. There's a white paper out there written by Ben Combee that explains in detail how to use Expanded Mode. It's titled "Supporting Expanded Mode on Palm OS". I could not find it on the web, so I put up a copy on my website: http://www.normsoft.com/tim/technical/Codewarrior_Expanded_Mode.pdf

Another more complicated option is to load the globals yourself and put a pointer to them in A5. In order to do this, you must modify (or duplicate) the Metrowerks startup code that loads globals and then call this modified code when you receive a non-global launch. Metrowerks includes the full source to this portion of the runtime, so you can do this pretty easily, though some of that code is pretty arcane. We successfully used this technique in one version of Pocket Tunes to access globals and an unlimited number of segments when called from a non-global launch code. Just be sure to restore A5 when returning from the launch code.

The final option is to move all (or some of) the code into PNOlets. This can be a pain because you have to segment your code into 68K and PNO, which can quickly become a nightmare to maintain. We've also successfully used this method, but the maintenance of the interworking code was awful. We finally ended up moving our entire code to a PNOlet using the PEAL loader, which works really well for large code because it automatically segments the code into 64KB chunks and runs the ARM code in-place. However, that is a very large effort because PNOlet development is not well-supported on ARM, so you have to provide a lot of low-level support yourself (like thunks for calling each API function).

怕倦 2024-07-13 08:55:16

使用 FtrSet 在 Ftr 内存中存储一​​个指向您使用 MemPtr 分配的大型结构的指针。 可以使用 FtrGet 在需要全局访问的应用程序中的任何位置检索此信息。

或者使用 __STANDALONE_CODE_RESOURCE__ 将每个函数放入单独的代码段中,并使用带有包装器的共享函数.c 将它们加载并锁定到内存中以调用它们。

//segment 1000

UInt32 foobar( char* hi )
{
   return 12;
}

// functions.c
typedef (UInt32)(*fooPtr)( char* ); // this is now a type representing a pointer to your function.
UInt32 foobar( char* hi )
{
   LocalID id; UInt16 cn; SysCurAppDatabase(&cn,&id);
   DmOpenRef ref = DmOpenDatabase (cn, id, dmModeReadOnly );
   MemHandle H = DmGetResource('code',1000);
   fooPtr code = MemHandleLock(H);
   UInt32 result = (*fooPtr)( hi);

   return result;
}

Store a pointer to a nice large structure you allocate with MemPtr in Ftr memory using FtrSet. This can be retrieved anywhere in your application that needs global access using FtrGet.

Alternately use __STANDALONE_CODE_RESOURCE__ to put each function into a seperate code segment and use a shared functions.c with wrappers to load and lock these into memory to call them.

//segment 1000

UInt32 foobar( char* hi )
{
   return 12;
}

// functions.c
typedef (UInt32)(*fooPtr)( char* ); // this is now a type representing a pointer to your function.
UInt32 foobar( char* hi )
{
   LocalID id; UInt16 cn; SysCurAppDatabase(&cn,&id);
   DmOpenRef ref = DmOpenDatabase (cn, id, dmModeReadOnly );
   MemHandle H = DmGetResource('code',1000);
   fooPtr code = MemHandleLock(H);
   UInt32 result = (*fooPtr)( hi);

   return result;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文