Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   UDFs y Delphi 2010 (https://www.clubdelphi.com/foros/showthread.php?t=67905)

Aldo 13-05-2010 09:18:57

UDFs y Delphi 2010
 
Hola a todos.

Estoy intentando desarrollar una DLL que tiene algunas funciones de usuarios para Firebird ( UDF ) y lo estoy programando en Delphi 2010.

El problema que presento es que una función debe devolver un PCHAR y en lugar de devolverme la cedena completa, solo me está devolviendo el primer carácter de dicha cadena.

Anteriormente tenía otra UDF similar programada con Delphi 5 y funciona correctamente.

Se que tiene algo que ver con el nuevo tratamiento de los Strigs y Pchars en Delphi 2010, pero la verdad es que no se me ocurre como solucionarlo.

Os agradezco de antemano el tiempo prestado por leer esto e intentar ayudarme.

Un saludo

Casimiro Notevi 13-05-2010 11:52:56

Será más fácil que alguien te pueda ayudar si pones el código de la función, no crees? ;)

Aldo 13-05-2010 12:48:26

OK. Creo que lo mejor es lo que dices.

Aquí os va part edel código que tiene una clase para tratar un String y poder convertirlo en Pchar para que sea devuleto por la UDF en cuestión.

Código Delphi [-]
...
Type
   TUDFString = class
  private
    FString: PChar;
    FSize: Integer;
    FLength: Integer;
    procedure SetPChar(Value: PChar);
    function GetString: String;
    procedure SetString(Value: String);
    procedure SetSize(Value: Integer);
  public
    constructor Create;
    destructor Destroy; override;
    property AsString: String read GetString write SetString;
    property AsPChar: PChar read FString write SetPChar;
    property StrLength: Integer read FLength;
    property StrSize: Integer read FSize write SetSize;
  end;
...
threadvar
  gResult: TUDFString;
...

implementation

const
  ShrinkLen = 100;

constructor TUDFString.Create;
begin
  FString := nil;
  SetSize(ShrinkLen);
  FLength := 0;
end;

destructor TUDFString.Destroy;
begin
  if (Self <> nil) and (FSize > 0) then
    ReallocMem(FString, 0);
  inherited;
end;

procedure TUDFString.SetPChar(Value: PChar);
begin
  FLength := StrLen(Value);
  SetSize(FLength);
  StrCopy(FString, Value);
end;

function TUDFString.GetString: String;
begin
  result := String(FString);
end;

procedure TUDFString.SetString(Value: String);
begin
  if Self <> nil then begin
    FLength := Length(Value);
    SetSize(FLength);
    StrPCopy(FString, Value);
  end;
end;

procedure TUDFString.SetSize(Value: Integer);
begin
  if (Value > FSize) or
     (Value <= FSize - ShrinkLen) then begin
    ReallocMem(FString, Value + 1);
    FSize := Value;
  end;
end;
...

Ahora la declaración de la UDF

Código Delphi [-]
function T_AlgoToStr( var nFVToCheck: Integer ): PChar; cdecl; export;

La implemetación de dicha función. Se asume que la variable gResult se ha creado en Initialization section de la DLL.

Código Delphi [-]
function T_AlgoToStr( var nFVToCheck: Integer ): PChar; cdecl; export;
   function IsValueOk( nValue: Integer ): Boolean;
   begin
      .....
      Result := True;
   end;
   
   function GetAlgoAsStr( nValue: Integer ): String;
   begin
      case nValue of
         1 : Result := 'Cadena 1' ;
         ...
         else
            Result := 'Cadena else';   
      end;
begin
   Result           := '';
   if  not IsValueOk( nFVToCheck ) then
      Exit;
   
   gResult.AsString := GetAlgoAsStr( nFVToCheck ); 
   Result           := gResult.AsPChar; 
end;

NOTA: Esto funciona correctamente en Delphi 5 pero no en Delphi 2010 que en vez de devolver la cadena completa solo devuelte el primer elemento de la cadena.

defcon1_es 13-05-2010 17:19:02

Cita:

Empezado por Aldo (Mensaje 363832)
NOTA: Esto funciona correctamente en Delphi 5 pero no en Delphi 2010 que en vez de devolver la cadena completa solo devuelte el primer elemento de la cadena.

Ciertamente es por lo que dices, en Delphi 2010 un PChar se trata como PWideChar.

Para evitar problemas con esto, deberías especificar el tamaño del caracter con el que estás trabajando (2 bytes), como he señalado en negrita.
Código Delphi [-]
procedure TUDFString.SetSize(Value: Integer);
begin
  if (Value > FSize) or
     (Value <= FSize - ShrinkLen) then begin
    ReallocMem(FString, (Value + 1) * Sizeof(WideChar));
    FSize := Value;
  end;
end;
...
No obstante, puedes mirar en la ayuda de Delphi 2010, ms-help://embarcadero.rs2010/rad/Enabling_Applications_for_Unicode.html

Otra buena referencia para trabajar con UNICODE la tienes aqui:
http://delphi.about.com/od/objectpas...-in-delphi.htm

Salu2

Aldo 14-05-2010 08:48:18

Muchas gracias por tu consejo, pero la verdad es que no se ha resuleto el problema con lo que me has comentado.

Hay algo que no he aclarado y es que he hecho una pequeña aplicación de testeo en la que he agregado la unit en la que está programada la función T_AlgoToStr y en ese caso SIEMPRE me ha funcionado bien, el problema es cuando ejecuto una sentencia SQL en el Marathon por ejemplo en la que involucro la función UDF, es solo ahí donde en vez de devolverme la cadena completa, me devuelve solamente la primera letra de la cadena.

Aclaro que uns función UDF similar programada en Delphi 5 funciona correctamente.

Por otra parte se me ha olvidado poner el ejemplo de la declaración de la función en el firebird 2.1 y es la siguiente:

Código SQL [-]
DECLARE EXTERNAL FUNCTION T_AlgoToStr
INTEGER
RETURNS CSTRING(255) 
ENTRY_POINT 'T_AlgoToStr' MODULE_NAME 'Library_UDF';

Intentaré seguir investigando. Pero agradezco cualquier tipo de ayuda, porque me urge el tema.

Un saludo


La franja horaria es GMT +2. Ahora son las 23:20:33.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi