Ver Mensaje Individual
  #2  
Antiguo 11-05-2012
LoPiTaL LoPiTaL is offline
Miembro
 
Registrado: abr 2009
Posts: 168
Reputación: 16
LoPiTaL Va por buen camino
Hola!
Cuando usas DLLs debes tener cuidado con el paso de parámetros que se crean / destruyen dinámicamente fuera de tu control, esto es, tipos de datos "managed", como por ejemplo strings. El compilador lleva internamente el conteo de las instancias de una string, de tal forma que cuando se deja de referenciar, la destruye automáticamente. Por eso se pueden hacer operaciones tipo 'mistring'+'miotrastring' y ya se encarga el compilador de crear una nueva string donde quepan todos los caracteres, etc...
Sin embargo, cuando trabajas con DLLs, el compilador deja de tener ese control sobre estos tipos de datos, por lo que si se le pasa a una DLL una cadena para que la almacene, y la función que llama deja de referenciar a esta cadena, ésta se destruirá provocando AV en la DLL, que cree que la cadena todavía existe. Es por esto por lo que con enteros te ha funcionado, pero con strings no.

El mismo RAD Studio te da información sobre ésto cuando creas una nueva DLL. En el archivo principal de la DLL te aparece el siguiente comentario:

Código Delphi [-]
{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

Esto se puede resolver evitando el paso de parámetros de tipo manejado. Esto es, reemplazando parámetros string, AnsiString, etc... por parámetros tipo PChar, PAnsiChar, etc... y en la DLL recrear la string mediante StrPas. De igual forma, el resultado devuelto NO debe ser manejado, por lo que deberías hacer lo mismo, devolver PChar y en la función llamante recrear la string con StrPas.

También se puede evitar si en lugar de DLLs usas BPLs, pero dejas de ser compatible con otros lenguajes.

Por otro lado, veo que no tienes bien definida la cabecera en Delphi. Si usas char * en C, debes usar PAnsiChar en Delphi (por lo que también tendrías resuelto el problema que te comento anteriormente). Y el resultado de la función es char (sin puntero), por lo que el resultado en Delphi deberá ser AnsiChar (sin la P).
Ahh! Y ojo con PChar y PAnsiChar, ya que en Delphi2007+ PChar es Unicode (puede ser 1, 2 ó 4 bytes), mientras que PAnsiChar es el de 1 byte de siempre.

Espero haberte ayudado.

Un saludo,
LoPiTaL
Responder Con Cita