2010-07-05 15 views
7

Subj. Me gustaría utilizar cadenas en lugar de PChar porque eso me ahorra mucho fundición, pero si acabo de hacer¿Es seguro pasar Delphi const string params a través de los límites del administrador de memoria?

procedure SomeExternalProc(s: string); external SOMEDLL_DLL; 

y luego ponerlo en práctica en algún otro proyecto no compartida con el Administrador de memoria:

library SeparateDll; 
procedure SomeExternalProc(s: string); 
begin 
    //a bla bla bla 
    //code here code here 
end; 

No tengo (formalmente) ninguna garantía Delphi no decide por ningún motivo alterar la cadena, modificar su contador de referencia, duplicarlo o único, o lo que sea. Por ejemplo

var InternalString: string; 

procedure SomeExternalProc(s: string); 
begin 
    InternalString := s; 
end; 

Delphi incrementa el refcounter y copia un puntero, eso es todo. Me gustaría que Delphi copiara los datos. ¿Declarar el parámetro como "const" lo hace seguro por esa razón? Si no, ¿hay alguna manera de hacerlo? La declaración de parámetro como PChar no parece ser una solución ya que es necesario para su emisión en cada ocasión:

procedure SomeExternalProc(s: Pchar); forward; 
procedure LocalProc; 
var local_s: string; 
begin 
    SomeExternalProc(local_s); //<<--- incompatible types: 'string' and 'PAnsiChar' 
end; 
+2

¿Por qué no quieres usar un MM compartido? Siempre que utilice el tipo de cadena, está obligado a Delphi, no puede ser una DLL genérica utilizable desde otros idiomas. ¿Por qué evitar compartir el MM? –

+0

El tipo de cadena es bastante compatible, puede ser interpretado por otros idiomas como PChar. No estoy hablando de devolver cuerdas, por supuesto, solo cadenas de params. – himself

+0

... o paquetes? –

Respuesta

13

que probablemente trabajar, siempre y cuando se utiliza de forma permanente el archivo DLL de código compilado en la misma versión de Delphi. Se sabe que el formato interno de cadena cambia entre lanzamientos, y no tiene garantía formal de que no vuelva a cambiar.

Si se quiere evitar tener que echar todas partes que lo utilice, trate de envolver la función, así:

procedure SomeExternalProc(s: Pchar); external dllname; 
procedure MyExternalProc(s: string); inline; 
begin 
    SomeExternalProc(PChar(local_s)); 
end; 

Luego, en el código, en lugar de llamar a MyExternalProcSomeExternalProc, y todo el mundo es feliz.

+0

Heh, me gana en menos de un minuto :) – gabr

+0

+1 debido a los detalles de control de versiones. Bueno. –

+0

Lo he estado haciendo durante un tiempo, pero al escribir todos estos apéndices ... (* editar: verificó el código generado para la versión en línea, sin addrefs después de todo *) – himself

6

Si la aplicación y la DLL están escritos en la misma versión de Delphi, simplemente use el administrador de memoria compartida (más detalles here).

Si un lado está escrito en un idioma diferente, no hay más remedio que usar PChar o WideString (WideStrings es administrado por el administrador de memoria COM).

O puede escribir una función de contenedor:

procedure MyExternalProc(const s: string); 
begin 
    SomeExternalProc(PChar(s)); 
end; 
-1

Recomiendo el uso de un administrador de memoria alternativa como RecyclerMM o FastMM. No requieren ningún dll MM externo compartido y le permite pasar cadenas a los dlls de forma segura. Como beneficio adicional, puede obtener una buena mejora de rendimiento en toda la aplicación.

FastMM se utiliza como administrador de memoria predeterminado en Delphi 2006 y posteriores. También es una buena herramienta para buscar fugas de memoria.

+0

Gracias, aunque sé todo eso. No estoy usando, o más precisamente, no * confiando * en mm compartidos porque quiero interoperabilidad, y también creo que depender de mm compartidos es un estilo malo: hace que te olvides de la gestión de memoria adecuada. – himself

+0

-1. Esto no es verdad. FastMM requiere que comparta el administrador de memoria para pasar cadenas de manera segura. Viene con una unidad llamada SimpleShareMem para lograr esto. Simplemente no hay forma de compartir la administración de cadenas de manera segura sin hacer que ambas fuentes usen el mismo montón. –

+0

Mason, ¿dónde dije algo así? Estaba escribiendo sobre la DLL externa (borlandmm.dll). Sí, SimpleShareMem es necesario si desea compartir la memoria entre aplicaciones que no usan FastMM y bibliotecas que usan FastMM. Pero estaba hablando de usar FastMM tanto en aplicaciones como en dll. – Andrew

0

sólo para añadir un solo hecho:

Delphi le permite asignar simplemente PChar a una cadena de modo en el lado DLL que no es necesario ningún encasillado:

function MyDllFunction(_s: PChar): integer; 
var 
    s: string; 
begin 
    s := _s; // implicit conversion to string 

    // now work with s instead of the _s parameter 
end; 

Esto también se aplica para el paso PChar como parámetro de una función que espera una cadena (por valor).

Cuestiones relacionadas