Ver Mensaje Individual
  #4  
Antiguo 16-01-2014
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Reputación: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
elmago00,

Revisa esta información:
Cita:
In general, functions in a DLL can use any type of parameter and return any type of value. There are two exceptions to this rule:
  • If you plan to call the DLL from other programming languages, you should try using Windows native data types instead of Delphi-specific types. For example, to express color values, you should use integers or the Windows ColorRef type instead of the Delphi native TColor type, doing the appropriate conversions (as in the FormDLL example, described in the next section). For compatibility, you should avoid using some other Delphi types, including objects (which cannot be used by other languages) and Delphi strings (which can be replaced by PChar strings). In other words, every Windows development environment must support the basic types of the API, and if you stick to them, your DLL will be usable with other development environments. Also, Delphi file variables (text files and binary file of record) should not be passed out of DLLs, but you can use Win32 file handles.
  • Even if you plan to use the DLL only from a Delphi application, you cannot pass Delphi strings (and dynamic arrays) across the DLL boundary without taking some precautions. This is the case because of the way Delphi manages strings in memory—allocating, reallocating, and freeing them automatically. The solution to the problem is to include the ShareMem system unit both in the DLL and in the program using it. This unit must be included as the first unit of each of the projects. Moreover, you have to deploy the BorlndMM.DLL file (the name stands for Borland Memory Manager) along with the program and the specific library.
Tomado del link : http://etutorials.org/Programming/ma...DLL+in+Delphi/
En el ejemplo del DLL propuesto en el Msg #3, No se siguieron las reglas descritas anteriormente dado que funciono correctamente en Delphi 2010 y Delphi XE4 (Asumo que también funcionaría en Delphi XE3), sin embargo en Delphi 7 los ejemplos descritos no funcionan correctamente, dado que en esta versión las reglas mencionadas son válidas.

En lo personal independientemente de la versión de Delphi que se utilice siempre es preferible seguir las reglas anteriores por compatibilidad con otros lenguajes en Windows, pero si el DLL y el programa son ambos programados en Delphi 2010 o Delphi XE4 (Solo menciono estas versiones por que son las que he probado en el ejemplo, pero lo más probable es que se cumpla de Delphi 2010 a Delphi XE5), es posible hacer el desarrollo del DLL y su programa asociado como se sugiere en el mensaje anterior en lo relacionado al uso de arreglos y strings como parámetros de un DLL.

Para evitar usar como parámetros Arreglos y Strings en Delphi DLLs, estos pueden ser sustituidos por medio de tipos PChar que permitan un medio confiable de intercambio de información entre diferentes lenguajes bajo Windows.

Revisa este código:
Código Delphi [-]
library TestDLL2;

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

{$R *.res}

function GetArraySim(Value : PChar) : PChar; stdcall;
var
   i : Integer;
   AuxStr : String;
   StrList : TStringList;

begin

   StrList := TStringList.Create;

   if (Value = 'Integer') then
   begin

      Randomize;

      for i := 0 to 9 do
      begin
         AuxStr := IntToStr(Random(1000));
         StrList.Add(AuxStr);
      end;

      Result := PChar(StrList.CommaText);

   end;

   if (Value = 'Double') then
   begin

      Randomize;

      for i := 0 to 9 do
      begin
         AuxStr := FormatFloat('##0.00',(Random(100)+Random));
         StrList.Add(AuxStr);
      end;

      Result :=PChar(StrList.CommaText);

   end;

   if (Value = 'String') then
   begin

      Randomize;

      for i := 0 to 9 do
      begin
         AuxStr := 'String-' + IntToStr(Random(1000));
         StrList.Add(AuxStr);
      end;

      Result :=PChar(StrList.CommaText);

   end;

   if (Value <> 'Integer') and (Value <> 'Double') and (Value <> 'String') then  
   begin
      MessageDlg('Error en String de Selección',mtInformation,[mbOK],0);
      Result := PChar(EmptyStr);
   end;

   StrList.Free;

end;

exports
   GetArraySim;

begin
end.
El código anterior en Delphi 7 bajo Windows 7 Professional x32, implementa un DLL que recibe un Pchar de entrada y devuelve un Pchar de salida que contiene varios items de tipo Integer, Double y String delimitados por coma, la idea es simular un arreglo de salida por medio de datos de tipo TStrinList y Pchar.

Revisa este código
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  function SimulaArray(Value : PChar) : PChar; stdcall; external 'TestDLL2.dll' name 'GetArraySim';

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   ComboBox1.Items.Add('Integer');
   ComboBox1.Items.Add('Double');
   ComboBox1.Items.Add('String');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   ArrInt : Array of Integer;
   ArrDbl : Array of Double;
   ArrStr : Array of String;
   i : Integer;
   Msg : String;
   StrList : TStringList;

begin

   Memo1.Clear;

   StrList := TStringList.Create;

   if ComboBox1.Text = 'Integer' then
   begin
      StrList.CommaText := SimulaArray(PChar(ComboBox1.Text));
      SetLength(ArrInt,StrList.Count);
      for i := 0 to StrList.Count-1 do
      begin
         ArrInt[i] := StrToInt(StrList.Strings[i]);
         Memo1.Lines.Add(IntToStr(ArrInt[i]));
      end;
   end;

   if ComboBox1.Text = 'Double' then
   begin
      StrList.CommaText := SimulaArray(PChar(ComboBox1.Text));
      SetLength(ArrDbl,StrList.Count);
      for i := 0 to StrList.Count-1 do
      begin
         ArrDbl[i] := StrToFloat(StrList.Strings[i]);
         Memo1.Lines.Add(FloatToStr(ArrDbl[i]));
      end;
   end;

   if ComboBox1.Text = 'String' then
   begin
      StrList.CommaText := SimulaArray(PChar(ComboBox1.Text));
      SetLength(ArrStr,StrList.Count);
      for i := 0 to StrList.Count-1 do
      begin
         ArrStr[i] := StrList.Strings[i];
         Memo1.Lines.Add(ArrStr[i]);
      end;
   end;

   StrList.Free;

end;

end.
El código anterior en Delphi 7 bajo Windows 7 Professional x32, implementa el DLL (TestDLL2) que simula el arreglo de salida indicado anteriormente.

De esta forma se pueden pasar gran cantidad de datos hacia y desde el DLL por medio de datos de tipo TStrinList y Pchar, otra forma es por medio de Estructuras Tipo Record por Referencia, pero solo en los casos que amerite este tipo de datos.

Espero sea útil

Nelson.

Última edición por nlsgarcia fecha: 16-01-2014 a las 03:49:40.
Responder Con Cita