Pregunta

la pregunta que tengo es: cuando ejecuto mi aplicación con un código de inicio que no sea sysAppLaunchCmdNormalLaunch, no puedo usar código fuera del segmento de código predeterminado, pero ¿podría usar una biblioteca compartida que esté multisegmentada, evitando así este problema? ?

Un poco de información básica: estoy evaluando la posibilidad de portar una aplicación móvil existente a PalmOS. Una parte central de esta aplicación es que está realizando algunas comunicaciones de red en segundo plano cada 10 minutos aproximadamente, o cuando recibe datos entrantes (a través de una devolución de llamada de red / socket). Durante este tiempo, no tengo acceso a los globales y, por lo tanto, a ningún segmento de código en mi aplicación que no sea el predeterminado.

El problema ahora es que las acciones involucradas en la comunicación (protocolo, manejo de datos, etc.) requieren una gran cantidad de código que simplemente no cabe en un segmento. Además de la pregunta de si tiene sentido ejecutar tanto código en segundo plano, el problema obvio es: ¿cómo lo ejecutaría en primer lugar? De ahí la pregunta, si ayudaría poner el código en una biblioteca compartida (de múltiples segmentos).

Esperamos sus ideas.

¿Fue útil?

Solución

No tengo experiencia en el uso de bibliotecas compartidas, pero hemos tenido este problema con nuestro software y hemos encontrado tres formas diferentes de resolver el problema.

Posiblemente lo más fácil es habilitar el modo expandido cuando se usa el compilador Metrowerks, pero no estoy completamente seguro de que esto funcione. Este modo especial le permite acceder a ciertos datos globales constantes cuando se llama desde un lanzamiento no global. Sin embargo, hay muchas advertencias para usar este enfoque. Además, no he confirmado que el modo expandido permita saltos entre segmentos con seguridad. Hay un libro blanco escrito por Ben Combee que explica en detalle cómo usar el modo expandido. Se titula " Soporte de modo expandido en Palm OS " ;. No pude encontrarlo en la web, así que puse una copia en mi sitio web: http://www.normsoft.com/tim/technical/Codewarrior_Expanded_Mode.pdf

Otra opción más complicada es cargar los globals usted mismo y ponerles un puntero en A5. Para hacer esto, debe modificar (o duplicar) el código de inicio de Metrowerks que carga los globales y luego llamar a este código modificado cuando reciba un lanzamiento no global. Metrowerks incluye la fuente completa de esta parte del tiempo de ejecución, por lo que puede hacerlo con bastante facilidad, aunque parte de ese código es bastante arcano. Utilizamos con éxito esta técnica en una versión de Pocket Tunes para acceder a los globales y a un número ilimitado de segmentos cuando se llama desde un código de lanzamiento no global. Solo asegúrese de restaurar A5 cuando regrese del código de inicio.

La opción final es mover todo (o algo de) el código a PNOlets. Esto puede ser una molestia porque debe segmentar su código en 68K y PNO, lo que puede convertirse rápidamente en una pesadilla para mantener. También hemos utilizado con éxito este método, pero el mantenimiento del código de interfuncionamiento fue horrible. Finalmente terminamos moviendo todo nuestro código a un PNOlet usando el cargador PEAL, que funciona realmente bien para código grande porque segmenta automáticamente el código en fragmentos de 64 KB y ejecuta el código ARM en el lugar. Sin embargo, ese es un esfuerzo muy grande porque el desarrollo PNOlet no está bien soportado en ARM, por lo que debe proporcionar una gran cantidad de soporte de bajo nivel (como thunks para llamar a cada función API).

Otros consejos

Almacene un puntero a una bonita estructura grande que asigne con MemPtr en la memoria Ftr usando FtrSet. Esto se puede recuperar en cualquier lugar de su aplicación que necesite acceso global utilizando FtrGet.

Utilice alternativamente __STANDALONE_CODE_RESOURCE__ para colocar cada función en un segmento de código separado y use un functions.c compartido con contenedores para cargar y bloquearlos en la memoria para llamarlos.

//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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top