Problem z BT Memory Module 0.0.1 i bass.dll.

0

Witam.

Czy ktoś z Was korzystał z BTMemoryModule_0.0.1, który może służyć do ładowania
dll'ek z zasobów do pamięci? Pytam, bo kombinuje jakby tutaj załadować sobie z
zasobów do pamięci bass.dll albo fmod.dll. Jednak obie zwracają errory przy
próbie wywołania prostej funkcji GetVersion czyli BASS_GetVersion dla biblioteki
bass.dll albo FSOUND_GetVersion dla fmod.dll. W przypadku tej pierwszej moduł
BTMemory nie zwraca żadnego konkretnego komunikatu o błędzie. W przypadku fmoda
jest to 'FinalizeSections: VirtualProtect failed'. Specialnie dla testów
dołączyłem do zasobów w pliku dane.res, testową dllke DemoDLL.dll, która jest
dołączona do źródeł modułu. A w pliku dane.rc zasoby zdefiniowane są tak:

bass_lib rcdata "bass.dll"
demo_lib rcdata "demodll.dll"

Kod mojego modułu poniżej. Kod w DemoDLLBtnClick działa poprawnie i DemoDll.dll
wywołuje dwa MessageBox'y z tekstem 'This is a Dll Memory call!' - natomiast to
co jest w BassDllBtnClick powoduje wyjatek Acess Violation - a po skompilowaniu
pokazuje error 'An error occoured while loading the dll: ' i tyle. Stąd pytanie
czy ten moduł będzie działał tylko z bibliotekami skompilowanymi w Delphi? No a
może akurat bass.dll jest jakoś tak stworzona, że działa poprawnie - załadowana
tylko i wyłącznie z dysku? Jakby ktoś mógł się przyjerzeć BT Memory to jest na:

http://www.joachim-bauch.de/tutorials/load_dll_memory.html
http://www.dsplayer.de/open_source_projects/BTMemoryModule.zip

A może znacie inny sposób na zamieszczenie biblioteki dll w zasobach - po czym
załadowanie jej do pamięci, tak aby działały wszystkie funkcje w niej zawarte?

unit main;

interface

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

type
  TTestCallstd = procedure(f_Text: PChar); stdcall;
  TTestCallcdel = procedure(f_Text: PChar); cdecl;
  TBASS_GetVersion = function : DWORD; stdcall;

  TForm1 = class(TForm)
    BassDllBtn: TButton;
    DemoDLLBtn: TButton;
    procedure FormDestroy(Sender: TObject);
    procedure BassDllBtnClick(Sender: TObject);
    procedure DemoDLLBtnClick(Sender: TObject);
  private
  public
    m_TestCallstd: TTestCallstd;
    m_TestCallcdel: TTestCallcdel;
    m_BassGetVer : TBass_GetVersion;
    mp_DllData: Pointer;
    m_DllDataSize: Integer;
    mp_MemoryModule: PBTMemoryModule;
    MemoryStream: TMemoryStream;
    Res_Stream : TResourceStream;
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

{$R dane.res}

procedure TForm1.BassDllBtnClick(Sender: TObject);
begin
  Res_Stream := TResourceStream.Create(Hinstance, 'bass_lib', RT_RCDATA);
  MemoryStream := TMemoryStream.Create;
  MemoryStream.LoadFromStream(Res_Stream);
  MemoryStream.Position := 0;
  m_DllDataSize := MemoryStream.Size;
  mp_DllData := GetMemory(m_DllDataSize);
  MemoryStream.Read(mp_DllData^, m_DllDataSize);
  MemoryStream.Free;

// Sama ta linia poniżej już generuje wyjątek bez konkrentnego tekstu błędu
  mp_MemoryModule := BTMemoryLoadLibary(mp_DllData, m_DllDataSize);

  try
    if mp_MemoryModule = nil then
      Abort;
  @m_BassGetVer := BTMemoryGetProcAddress(mp_MemoryModule, 'BASS_GetVersion');

  ShowMessage(IntToStr(m_BassGetVer));
  except
    Showmessage('An error occoured while loading the dll: ' +
      BTMemoryGetLastError);
  end;
end;

procedure TForm1.DemoDLLBtnClick(Sender: TObject);
begin
Res_Stream := TResourceStream.Create(Hinstance, 'demo_lib', RT_RCDATA);
  MemoryStream := TMemoryStream.Create;
  MemoryStream.LoadFromStream(Res_Stream);
  MemoryStream.Position := 0;
  m_DllDataSize := MemoryStream.Size;
  mp_DllData := GetMemory(m_DllDataSize);
  MemoryStream.Read(mp_DllData^, m_DllDataSize);
  MemoryStream.Free;

  mp_MemoryModule := BTMemoryLoadLibary(mp_DllData, m_DllDataSize);
  try
    if mp_MemoryModule = nil then
      Abort;
    @m_TestCallstd := BTMemoryGetProcAddress(mp_MemoryModule, 'TestCallstd');
    if @m_TestCallstd = nil then
      Abort;
    @m_TestCallcdel := BTMemoryGetProcAddress(mp_MemoryModule, 'TestCallcdel');
    if @m_TestCallcdel = nil then
      Abort;
    m_TestCallstd('This is a Dll Memory call!');
    m_TestCallcdel('This is a Dll Memory call!');
  except
    Showmessage('An error occoured while loading the dll: ' +
      BTMemoryGetLastError);
  end;
  if mp_MemoryModule <> nil then
    BTMemoryFreeLibrary(mp_MemoryModule);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeMemory(mp_DllData);
end;

end.
0

I jak Olesio? Rozwiązałeś problem z biblioteką ładowaną z zasobów?

0

Tak, już dawno. Jednak strona z potrzebnym i dzialającym bez problemow modułem padła.
Dlatego wrzuciłem archiwum - z jednym narzędzien static2dyndll.exe - poprawionym przez
siebie na: http://www.mediafire.com/file/65y9x36pt8vhuvo/dlltools.rar link nie wygaśnie.
Z moich testów wynika, że moduł dllloader.pas działa z różnymi bibliotekami, bez żadnych
problemów - chociaż głownie testowalem go na bass.dll oraz sqlite3.dll no i się sprawdził.

0

Świetnie. Potestuje z biblioteką IJL i dam znać jak to działa.
I jeszcze jedno pytanie. Czy te rozwiązanie działa na wszystkich Windowsach tzn. od XP do 7?

0

Tego nie mam jak sprawdzić w tej chwili, ale na XP działa na pewno. Podejrzewam,
że na nowszych także, bo napisałem kiedyś prosty klon gry "5x5", gdzie w nowszej
wersji bass.dll jest wczytywany z zasobów tym modułem, do którego link podałem i,
o ile się orientuje znajomy testujący grę - nie miał problemow na Viście i siódemce.
Na pewno przy skompilowaniu pod Delphi 7 Personal - nie stwierdziłem problemów.

0

No to jestem dobrej myśli. Dzięki za informacje.

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