Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Рабочая функция генерит ошибку


Автор: Poseidon 15.9.2005, 18:13
Вот незадача.
Есть функция, каторая при помещении ее в .exe работает на УРА. Но стоит ее поместить в Dll, как все летит.

Dll:
Код
library Lan;

uses
  SysUtils,
  WinSock;

{$R *.res}

function HostToIP(name: string): string; stdcall;
var
  wsdata : TWSAData;
  hostName : array [0..255] of char;
  hostEnt : PHostEnt;
  addr : PChar;
begin
  WSAStartup ($0101, wsdata);
  try
    gethostname (hostName, sizeof (hostName));
    StrPCopy(hostName, name);
    hostEnt := gethostbyname (hostName);
    if Assigned (hostEnt) then
      if Assigned (hostEnt^.h_addr_list) then begin
        addr := hostEnt^.h_addr_list^;
        if Assigned (addr) then begin
          Result := Format ('%d.%d.%d.%d', [byte(addr[0]),
          byte (addr [1]), byte (addr [2]), byte(addr[3])]);
        end
        else
          Result := '';
      end
      else
        Result := ''
    else begin
      Result := '';
    end;
  finally
    WSACleanup;
  end
end;


exports
HostToIP;

begin
end.


.exe

Код
unit Unit1;

interface

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

type THostToIP = function (name: string): string; stdcall;

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
HostToIP: THostToIP;
LanDll: THandle;
begin
LanDll:= LoadLibrary('Lan.dll');
@HostToIp:= GetProcAddress(LanDll, 'HostToIP');
Form1.Caption:= HostToIP('');
FreeLibrary(LanDll);
end;

end.


C чего бы это? smile

Автор: p0s0l 15.9.2005, 18:43
Помести ShareMem в USES-часть DLL-ки и USES-часть проекта (*.dpr). Важная деталь: ShareMem должен быть первым в списке подключаемых модулей!
Добавлено @ 18:52
Цитата(Poseidon @ 15.9.2005, 18:13)
C чего бы это?
Когда делаем File->New->Other->DLL Wizard:
Код

library Project1;

{ 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. }

uses
  SysUtils,
  Classes;

{$R *.res}

begin
end.


Автор: Poseidon 15.9.2005, 18:54
Спасибо p0s0l, но это вариант не подойдет по двум причинам:
1). Размер ДЛЛ увеличился с 91 до 234 Кб. (У лучше тогда подключить WinSock к exe и создать функцию там)
2) Функция выполняется, но при закрытии программы вылетает "Invalid pointer operation"

Мне даже не нужно готовый рабочий пример давать. Мне бы понять, почему так происходит. Ведь, если эта функция зашита в exe, то все нормально работает.

Понять бы почему ошибка, тогда и разобратся с ней было бы легче.

PS. А что это за модуль такой ShareMem? Зачем он?

Автор: p0s0l 15.9.2005, 19:03
Цитата(Poseidon @ 15.9.2005, 18:54)
2) Функция выполняется, но при закрытии программы вылетает "Invalid pointer operation"
Значит не туда или не везде воткнул ShareMem...

Цитата(Poseidon @ 15.9.2005, 18:54)
PS. А что это за модуль такой ShareMem? Зачем он?
Цитата(Help)
ShareMem is the interface unit for the BORLANDMM.DLL memory manager, which allows modules to share dynamically allocated memory.
Более подробно - открой DRKB и в поиске напиши ShareMem smile
Например:
Цитата(DRKB)
Первый вопрос возникающий при создании библиотеки (DLL): А что это тут написано в закомментированной части исходного кода библиотеки. А рассказывается там следующее — если вы используете динамические массивы, длинные строки (что и является динамическим ма ссивом) как результат функции, то необходимо чтобы первым в секции uses стоял модуль ShareMem. Причём и в основном проекте! От себя добавлю, что это относится более широко к тем случаям, когда вы выделяете память в одной библиотеке, а освобождаете в друго й, что и произойдёт когда вы создадите динамический массив в одной Dll-ке, а освободите его в другой.

Использовать ли ShareMem — вопрос конкретной постановки задачи. Если можно обойтись без таких выделений памяти, то вперёд, с песней! Иначе придётся вместе с программой таскать borlndmm.dll, которая и реализует безболезненный обмен указателями между библио теками.


Цитата
1). Размер ДЛЛ увеличился с 41 до 234 Кб. (У лучше тогда подключить WinSock к exe и создать функцию там)
Тогда придётся отказаться от передачи динамических строк и массивов... Самое простое - в общем случае передавать в функцию адрес буфера (ну и размер буфера), куда функция должна поместить результат...
В твоём же случае (IP-адрес и имя машины) можно использовать ShortString вместо string...
Добавлено @ 19:10
Так же Петрович когда-то упоминал альтернативу ShareMem - FastSharemem, тогда DLL-ку с собой таскать не надо... Я не юзал, но можешь попробовать...

Автор: Poseidon 15.9.2005, 19:17
Благодарствую. Немного покапавшись в указанном табою направлении с ошибкой справился. smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)