[beendet]Ressourcen in die ausführbare Datei hinein kompilieren

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
oliver2104
Beiträge: 48
Registriert: Sa 26. Dez 2020, 13:22

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von oliver2104 »

Vielen Dank,
programmiere nur zum Spaß und es kann schon ein paar Tage dauern bis ich mich da (TStream-Konzept) durchgearbeitet habe.
Befürchte nur, da wird gleich der Datei-inhalt eingelesen.
SDL braucht aber nur den Dateiname bzw. -pfad und liest dann den Inhalt mit eigenen Kommandos ein
Beispiel : Font einlesen

Code: Alles auswählen

const
  font_path = 'Cousine-Bold.ttf';    // Fontfile im Sourcecode Verzeichnis
var
  ttfFont : PTTF_Font;    // pointer to TTF_Font that holds the font’s data  ( SDL DatenTyp)
  
procedure FontEinlesen;
begin
  ttfFont:= TTF_OpenFont(font_path, fontsize);  //  SDL Befehl (TTF_OpenFont) braucht Dateiname und Darstellungsgröße
end;
Melde mich wieder.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1639
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von fliegermichl »

In dem Link weiter oben (Lazarus Wiki) wird eine Resource in eine externe Datei gespeichert.
Das kannst du als Basis nehmen und so die Dateien selbst erzeugen.

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Zvoni »

fliegermichl hat geschrieben: Do 31. Okt 2024, 14:15 In dem Link weiter oben (Lazarus Wiki) wird eine Resource in eine externe Datei gespeichert.
Das kannst du als Basis nehmen und so die Dateien selbst erzeugen.
Jepp. Resourcen in Datei auslagern, dein SDL-Gedöns aufrufen, wieder löschen

Code: Alles auswählen

program mydata;
uses
  SysUtils, Classes, LCLType;
{$R mydata.res}
var
  S: TResourceStream;
  F: TFileStream;
begin
  // create a resource stream which points to our resource
  S := TResourceStream.Create(HInstance, 'MYFONT', RT_RCDATA);
  // Please ensure you write the enclosing apostrophes around MYDATA, 
  // otherwise no data will be extracted.
  try
    // create a file in the application directory
    F := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'myfont.ttf', fmCreate); 
    try
      F.CopyFrom(S, S.Size); // copy data from the resource stream to file stream
    finally
      F.Free; // destroy the file stream
    end;
  finally
    S.Free; // destroy the resource stream
  end;
end.
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Mathias
Beiträge: 6900
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Mathias »

Das hab ich schon weiter oben im Thread gesagt.
es geht um ein SDL2 Projekt (das bräuchte keine LCL Komponenten)
Was es aber braucht sind einige (*.mp3, *.png und *.ttf) Dateien.
Die möchte ich gerne mit hinein kompilieren. Wie ist eigentlich egal.
Mein Ziel wäre es, nur die ausführbare Datei (mit einkompilierten Ressourcen) an andere weiterzugeben.
Möchte die Ressoucen nicht als *.mp3, *.png und *.ttf weitergeben. (kann jeder verändern und das Prog läuft dann ev. gar nicht mehr wie gewünscht)
Dies müsste eigentlich mit SDL, anstelle einer Datei, kann man SDL auch eine Buffer mitgeben. Im Falle eine MP* wäre dies dann.

Code: Alles auswählen

function Mix_LoadWAV_IO(src: PSDL_IOStream; closeio: TSDL_bool): PMix_Chunk; cdecl; external sdl3_mixer_lib;
Du musst nur deinen DatenBuffer in einen PSDL_IOStream kopieren. Von wo die Daten kommen ist egal, in deinem Fall von einer Resource.
Befüllen tut man den Stream mittels:

Code: Alles auswählen

function SDL_IOFromMem(mem: pointer; size: Tsize_t): PSDL_IOStream; cdecl; external libSDL3;
Ich habe die nie probiert, aber dies wäre der Lösungsweg.

Ups, habe gerade gesehen, das die nur mit SDL3 geht. Bei SDL2 müsstes du dich mit SDL_RWops schlau machen.
Aber du darfst auch gern mein SDL3 Header ausprobieren.
viewtopic.php?f=29&t=15793&p=144933&hilit=sdl3#p144933
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6900
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Mathias »

Ich konnte es nicht lassen und es funktioniert über SDL_IOStream.
Das mit dem Ansistring ist recht unschön, dam müsste man ein ByteArray verwenden.

Code: Alles auswählen

function FileToStr(const path: string): ansistring;
var
  f: file of byte;
  size: int64;
begin
  Result := '';
  if FileExists(path) then begin
    Assign(f, path);
    Reset(f);
    size := FileSize(f);
    SetLength(Result, size);
    BlockRead(f, Result[1], size);
    Close(f);
  end else begin
    WriteLn('FEHLER: Kann Datei ' + path + ' nicht finden');
  end;
end;

var
  buffer: string;

procedure TForm1.FormCreate(Sender: TObject);
var
  stream: PSDL_IOStream;
begin
  buffer := FileToStr('/home/tux/Schreibtisch/sound/test.mp3');

  stream := SDL_IOFromConstMem(Pointer(buffer), Length(buffer));
  if stream = nil then begin
    WriteLn('stream error: ', SDL_GetError);
  end;

  SDL_Init(SDL_INIT_AUDIO);
  WriteLn(Mix_OpenAudio(0, nil));

  music := Mix_LoadMUS_IO(stream, True);
  if music = nil then begin
    WriteLn('error music: ', Mix_GetError);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Mix_FadeInMusic(music, 1, 3000);
end;
Ich vermute, das es auch mit einer Resource geht.

Code: Alles auswählen

function ResourceToStr(Resource: string): ansistring;
var
  rs: TResourceStream;
  pc10: PChar = nil;
begin
  rs := TResourceStream.Create(HINSTANCE, Resource, pc10);
  SetLength(Result, rs.Size);
  rs.Read(PChar(Result)^, rs.Size);
  rs.Free;
end;
Das hier Ansistring verwendet wird, das es Routinen waren, um OpenGL-Shader hoch zu laden. Und diese sind in Form eines Stringes.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

oliver2104
Beiträge: 48
Registriert: Sa 26. Dez 2020, 13:22

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von oliver2104 »

Puhhh, das waren jetzt viele nützliche Infos !
Bin wie gesagt kein Profi und befürchte das kann ev. Wochen dauern bis ich da durch bin.
An manchen Tagen macht's Spass daran weiter zu arbeiten an manchen Tagen nicht.
Melde mich wieder wenn's bei mir Fortschritte gibt
Vielen Dank !

Mathias
Beiträge: 6900
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Mathias »

Bin wie gesagt kein Profi und befürchte das kann ev. Wochen dauern bis ich da durch bin.
Das Prinzip ist eigentlich sehr einfach, anstelle die Daten direkt von Disc zu laden, gibst du SDL die Daten direkt vom einem RAM-Buffer mit.

Für die ersten Versuche würde ich die Daten mal so hoch laden, egal ob MP3 oder eine Images.
Und dann kann du mal mit dem IOStream von SDL spielen.

Code: Alles auswählen

function FileToByteBuffer(const path: string): TCharArray;
var
  f: file of byte;
  size: int64;
begin
  Result := nil;
  if FileExists(path) then begin
    Assign(f, path);
    Reset(f);
    size := FileSize(f);
    SetLength(Result, size);
    BlockRead(f, Result[0], size);
    Close(f);
  end else begin
    WriteLn('FEHLER: Kann Datei ' + path + ' nicht finden');
  end;
end;
Wen dies mal klappt, kannst du es immer noch über die Resourcen machen.
Ich habe es gestern mal so probiert und es funktionierte.

Code: Alles auswählen

function ResourceToByteBuffer(Resource: string): TCharArray;
var
  rs: TResourceStream;
begin
  Result := nil;
  rs := TResourceStream.Create(HINSTANCE, Resource, RT_RCDATA);
  SetLength(Result, rs.Size);
  rs.Read(PChar(Result)^, rs.Size);
  rs.Free;
end;  
Für Windows muss einfach noch die unit windows eingebunden werden.

Code: Alles auswählen

uses
  {$IFDEF MSWINDOWS}
  Windows,
  {$ENDIF}
SDL-Seitig kannst du es dann so hoch laden.

Code: Alles auswählen

var
  buffer: TCharArray;

procedure TForm1.FormCreate(Sender: TObject);
var
  stream: PSDL_IOStream;
begin
  //  buffer := FileToByteBuffer('/home/tux/Schreibtisch/sound/test.mp3');
  // oder
  buffer := ResourceToByteBuffer('MP3');

  stream := SDL_IOFromConstMem(Pointer(buffer), Length(buffer));
  if stream = nil then begin
    WriteLn('stream error: ', SDL_GetError);
  end;

  SDL_Init(SDL_INIT_AUDIO);
  WriteLn(Mix_OpenAudio(0, nil));

  music := Mix_LoadMUS_IO(stream, True);
  if music = nil then begin
    WriteLn('error music: ', Mix_GetError);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Mix_FadeInMusic(music, 1, 3000);
end;    
Was noch wichtig ist, der Buffer muss global deklariert sein, weil SDL den braucht, bis man den Stream mit SDL_CloseIO beendet.

Das ist ein Vorteil von SDL man kann für alles den IOStrem verwenden, egal ob Musik, Images, etc.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

oliver2104
Beiträge: 48
Registriert: Sa 26. Dez 2020, 13:22

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von oliver2104 »

Es wird schon so sein, das SDL alle Funktionen mitbringt die benötigt werden.
Bei SDL fehlt mir aber ein umfassendes Tutorial um alles zu verstehen.
Was ich über SDL weiß, kommt von den Tutorials auf https://www.freepascal-meets-sdl.net/
Ein SDL-freepascal-Forum hab ich auch nicht gefunden und C möchte ich mir nicht antun.
Würde euch gerne mal mein Programm ansehen lassen, es ist so eine Art Space-Taxi Spiel.
Kann man hier im Forum *.zip Dateien ablegen ?

Mathias
Beiträge: 6900
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Mathias »

Ein SDL-freepascal-Forum hab ich auch nicht gefunden und C möchte ich mir nicht antun.
Ein Forum wir man kaum finden, da es im englischen schon recht ruhig ist.
Wobei einem dort gut geholfen wird.

Wen du nur ein wenig C lesen kannst, kann man die Tutorials von C sehr gut auf Pascal umsetzen.
Dies mache ich auch so.
SDL-Header für Pascal gibt es schon fertige. SDL1.x ist bei FPC dabei, SDL2.x, gibt es auch was. Und ich bin gerade am pflegen von SDL3.x

Kann man hier im Forum *.zip Dateien ablegen ?
Ja dies geht, wen die Datei nicht zu gross ist. Als Anhang.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

oliver2104
Beiträge: 48
Registriert: Sa 26. Dez 2020, 13:22

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von oliver2104 »

Danke,
die SDL2 Header für Pascal Header habe ich schon. Auf SDL3 kann ich ruhig noch warten.
Hab jetzt mal versucht mein Programm als .zip anzuhängen, nur damit man sieht worums geht.
Werde jetzt noch einige Zeit herumbasteln um die Ressourcen einzukompilieren,
wenn ich's nicht schaffe ist das auch kein großes Problem.
sdl_lander_win.zip
Windows Version
(2.15 MiB) 48-mal heruntergeladen

oliver2104
Beiträge: 48
Registriert: Sa 26. Dez 2020, 13:22

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von oliver2104 »

Hallo,
sehr gut gefällt mir der Vorschlag von Sieben, die Dateien über Projekt -> Optionen -> Ressourcen einzugeben.
Nach kompilieren hab ich dann eine .res Datei welche ich dann im SourceCode mit {$R *.res} ins .exe reinkompilieren kann.
Ohne Hilfsprogramme wie lazres, windres oder .rc Dateien usw.
Also reinkompilieren wäre geschafft. Aber wie kann ich das in meinem SourceCode verwenden ?

Mit dem Stream Konzept kann ich dzt. noch nichts anfangen
In dem Link weiter oben (Lazarus Wiki) wird eine Resource in eine externe Datei gespeichert.
Das kannst du als Basis nehmen und so die Dateien selbst erzeugen.
Hab die einzelnen Ressourcenfiles, meinen SourceCode und jetzt das ensprechende .res File.
Möchte nur die mit {$R *.res} eingebundenen Daten im SourceCode verwenden.
Weitere externe Dateien bräuchte ich eigentlich nicht.

Mathias
Beiträge: 6900
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Mathias »

Also reinkompilieren wäre geschafft. Aber wie kann ich das in meinem SourceCode verwenden ?
Ganz einfach, die Daten sind nach dem Laden mit

Code: Alles auswählen

rs.Read(PChar(Result)^, rs.Size);
in einem Buffer.
Ich habe jetzt als Beispiel bei Project->Einstellungen->Resourcen anstelle der MP3 die unit.pas genommen.

Und so kann ich den Buffer in eine TMemo kopieren.

Code: Alles auswählen

function ResourceToByteBuffer(Resource: string): TCharArray;
var
  rs: TResourceStream;
begin
  Result := nil;
  rs := TResourceStream.Create(HINSTANCE, Resource, RT_RCDATA);
  SetLength(Result, rs.Size);
  rs.Read(PChar(Result)^, rs.Size);
  rs.Free;
end;

var
  buffer: TCharArray;

procedure TForm1.FormCreate(Sender: TObject);
begin
  buffer := ResourceToByteBuffer('UNIT1');
  Memo1.Text := string(buffer);
end;
Im Prinzip beinhaltet in meinem Beispiel der buffer den gleichen Inhalt wie die Datei auf der Platte.
Im Beispiel mit der MP3, ist im Buffer auch der ganze MP3-Header, so wie es auf der Disc ist.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Sieben
Beiträge: 289
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Sieben »

...sehr gut gefällt mir der Vorschlag von Sieben, die Dateien über Projekt -> Optionen -> Ressourcen einzugeben.
Nach kompilieren hab ich dann eine .res Datei welche ich dann im SourceCode mit {$R *.res} ins .exe reinkompilieren kann.
Dann hast du sie aber gleich zweimal drin bzw überschreibst sie nochmal mit sich selbst. Die Ressourcen, die du auf diesem Weg hinzufügst, werden von Lazarus automatisch in die exe übernommen.

Mathias
Beiträge: 6900
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von Mathias »

Nach kompilieren hab ich dann eine .res Datei welche ich dann im SourceCode mit {$R *.res} ins .exe reinkompilieren kann.
Da habe ich gerade etwas unlogisches entdeckt. Da wird *.res für die Resourcen verwendet. Uns wen man ein SIGSEV auslöst, gibt es auch solch eine Datei.
Zum verwechseln ähnlich !
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

oliver2104
Beiträge: 48
Registriert: Sa 26. Dez 2020, 13:22

Re: Ressourcen in die ausführbare Datei hinein kompilieren

Beitrag von oliver2104 »

Ehrlich gesagt wird mir das ganze zu kompliziert bzw. ist mir den ganzen Aufwand nicht Wert.
Das Programm läuft ohnehin, das Einkompilieren der Ressourcen hätte alles nur ein wenig abgerundet.
Bevor ich mir an dem Detail die Zähne ausbeisse, überleg ich mir lieber ein komplett neues Programm.
Ich möchte aber allen Danke sagen, die ihre Zeit geopfert haben um mir Tips zu geben !

Antworten