Aplikacja + Biblioteka z dynamicznie ładowaną funkcją w TTimer

0

Mam taki dziwny problem, nie wiem co jest jego powodem...
Otóż, mam aplikację, która wywołuje funkcje z biblioteki. Funkcje ładowane są dynamicznie (ponieważ z biblioteki korzystają 2 programy, w różnych
lokalizacjach). Funkcje w programie odpalane są co określony czas w TTimer.

Problem: TTimer ustawiony jest w przedziale 500-1000ms. Gdy chcę przesunąć formę lub zmienić jej rozmiar, bądź rozwinąć jakąś listę na tej formie,
aplikacja nie zezwala na to - jakby traciła fokus. Rozumiem, że to przez cykliczne wywoływanie funkcji z biblioteki, ale nie wiem dlaczego tak jest i co robię źle.
Poniżej szkielet tego co mam:

Biblioteka:

library System;

uses
  Windows,
  SysUtils,
  Classes;

{$R *.res}

// Current Data ------------------------------------------------------------------------------------
function GetCurrent_Data: PChar; stdcall;
begin
   result:=PChar(DateToStr(Now));
end;
// Current Data ------------------------------------------------------------------------------------

// Current Time ------------------------------------------------------------------------------------
function GetCurrent_Time: PChar; stdcall;
begin
   result:=PChar(TimeToStr(Now));
end;
// Current Time ------------------------------------------------------------------------------------

exports
  GetCurrent_Data,
  GetCurrent_Time;

begin
end.

Jak widać, biblioteka eksportuje 2 proste funkcje, które zwracają bieżącą datę i godzinę.

Program (w uproszczeniu)


type
   TGetCurrent_Data_Func = function : PChar; stdcall;
   TGetCurrent_Time_Func = function : PChar; stdcall;

var
   DLL_Handle                  : Cardinal;
   GetCurrent_Data_Func   : TGetCurrent_Data_Func;
   GetCurrent_Time_Func   : TGetCurrent_Time_Func;
   V_CurrentData          : string;
   V_CurrentTime          : string;
...

// procedura, która ładuje biblioteke i odpala 2 funkcje
procedure TMainFrm.Load_System_Info;
begin
   DLL_Handle := LoadLibrary(PWideChar('C:\MyLibraryPath\System.dll')) ;
   if DLL_Handle <> 0 then
      begin
          try
            // Current Date
            @GetCurrent_Data_Func := GetProcAddress(DLL_Handle, 'GetCurrent_Data');
            if Assigned (GetCurrent_Data_Func) then
               begin
                  V_CurrentData:= GetCurrent_Data_Func; // wynik funkcji wędruje do zmiennej globalnej
               end;

            // Current Time
            @GetCurrent_Time_Func := GetProcAddress(DLL_Handle, 'GetCurrent_Time');
            if Assigned (GetCurrent_Time_Func) then
               begin
                  V_CurrentTime:= GetCurrent_Time_Func; // wynik funkcji wędruje do zmiennej globalnej
               end;

          finally
             FreeLibrary(DLL_Handle);
          end;
      end;
end;

...
// Odpalam co 500 ms

procedure TMainFrm.TimerTimer(Sender: TObject);
begin
     Load_System_Info;
end;

Co robię źle?
-Pawel

0

Takie coś: result:=PChar(DateToStr(Now));
Nie będzie działać nawet bez DLL, zwracaj string oraz użyj tego: http://borland.newsgroups.archived.at/public.delphi.language.delphi.win32/200701/0701296796.html

0

Tu nie powinno się nic złego dziać jak zakomentujesz Load_System_Info; to problem znika?
Kolejna sprawa nie możesz w ten sposób zwracać string'a - powinieneś zrobić raczej coś takiego:
http://stackoverflow.com/questions/4269622/in-delphi-in-my-dll-do-i-have-to-allocate-the-return-pchar-of-a-function
Po wyjściu z funkcji napis jest usuwany.

Ponadto:
data to po angielsku dane
date to po angielsku data

0

Zrobiłem test z ładowaniem statycznym. Wtedy jest OK (ale minusem jest tutaj konieczność wrzucenia dll do katalogu programu lub do którejś z lokalizacji przeglądanej przez system). Zatem problem występuje tylko, gdy próbuję załadować funkcję z biblioteki dynamicznie.
Btw, czy jest jakiś sposób, aby załadować bibliotekę statycznie - ale móc określić lokalizację tej biblioteki?
-Pawel

0

Też możesz podać ścieżkę do dll z tym, że musi być podana na sztywno w programie.
przykład ładujący bibliotekę libeay32.dll z folderu dll:

const
  LIBEAY_DLL_NAME = 'dll\libeay32.dll';

type
  TOpenSSL_InitFunction = procedure; cdecl;

function SSLeay: cardinal; external LIBEAY_DLL_NAME;
function SSLeay_version; external LIBEAY_DLL_NAME;

Wracając do twojego kodu zauważyłem, że używasz zmiennych globalnych czy oprócz tego miejsca z tych zmiennych korzystają też inne funkcje? Może inny timer zmienia uchwyt do dllki w tym samym czasie?

0

Niestety, sztywna ścieżka nic nie daje (choć od biedy mógłbym użyć, bo akurat w projekcie który używam ścieżki względne 2 programów, które używają biblioteki się nie zmienią). Ale wolę elastyczne rozwiązania. Dynamiczne ładowanie funkcji, w momencie kiedy chce to idealne rozwiązanie, ale niestety napotkalem ten dziwny problem. Częściowo rozwiązałem problem, przechwytując komunikaty WMEnterSizeMove, WMExitSizeMove (gdy przesuwam forme, zmieniam rozmiar wstrzymuje wykonywanie funkcji - może mało eleganckie, ale na ten czas działa).
Użyłem w powyższym przykładowym kodzie tych zmiennych jako globalnych, ale wcale takie nie muszą być. Nic innego nie działa w tym czasie. Specjalnie maksymalnie uprościłem kod, żeby być pewnym, że nic innego nie ma wpływu na to...
Chyba zmienię na ładowanie statyczne i wrzucę dllke do \system32. A ShareMem i bibliotekę borlndmm.dll zastąpię modułem FastSharemem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1