Archiv verlassen und diese Seite im Standarddesign anzeigen : Daten statisch linken
Yonibear
26-05-2006, 21:42
Hi!
Wie kann ich eigentlich Dateien statisch in eine executable linken?
Ich möchte die Daten für ein Spiel nicht nachladen müssen, sondern über Zeiger direkt auf sie zugreifen als hätte ich sie selber im Code definiert. Da das aber etwas mühsam wäre, suche ich nach einer Möglichkeit normale Dateien als Symbol zu linken.
mfg yonibear
Wenn du eine Bibliothek statisch linken willst brauchst du die Linker Option -static.
Was meinst du jetzt genua mit Daten?
Irgendwelche Einstellungen, die du in einer (Text)Datei gespichert hast und zur Laufzeit des Programms daruas auslesen würdest?
peschmae
27-05-2006, 12:28
Ich denke mal er meint z.B. Bitmaps oder so.
MfG Peschmä
Also so'n Zeug was bei Windows mit diesem ominösen "Ressourcen" gemacht wird?
Yonibear
27-05-2006, 13:03
Genau das mein ich. Ich will zb. einen als extern deklarierten Pointer als Zeiger auf eine hinzugelinkte Datei auflösen.
Genau das mein ich. Ich will zb. einen als extern deklarierten Pointer als Zeiger auf eine hinzugelinkte Datei auflösen.Find ich nicht gut, denn das ist ja dann während der Laufzeit des Programmes im Speicher. Wenn du die so "eingelinkte" Datei dann einliest sind die daten zwei mal im Speicher!!
Aber theoretisch würde es gehn, indem du mit einen skript die Datein in einen c-string umwandelst und deren größe auch in ner variable speicherst.
Man könnte z.B. so ein python skript dafür machen und das dann aus der makefile aus aufrufen:
#!/usr/bin/env python
import os,sys,string
def esc(s):
L = []
prt = set(string.printable)
for c in s:
if c == '\\':
L.append('\\\\')
elif c == '"':
L.append('\\"')
elif c == "'":
L.append("\\'")
elif c == '\n':
L.append('\\n')
elif c == '\r':
L.append('\\r')
elif c == '\v':
L.append('\\v')
elif c == '\t':
L.append('\\t')
elif c in prt:
L.append(c)
else:
L.append('\\x%02x' % ord(c))
return ''.join(L)
cname = sys.argv[1]
fname = sys.argv[2]
CNAME = cname.upper()
fin = open(fname,"rb")
fout = open(cname + ".h","w")
fout.write(
"""\
#ifndef %(NAME)s_H__
#define %(NAME)s_H__
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
size_t %(name)s_size = %(size)d;
const char * %(name)s_data =
"""
%
{
'NAME': CNAME,
'name': cname,
'size': os.path.getsize(fname)
}
)
while True:
s = fin.read(80)
if not s:
break
fout.write('"%s"\n' % esc(s))
fout.write(
"""\
"";
#ifdef __cplusplus
}
#endif
#endif /* %s_H__ */
""" % CNAME)
fin.close()
fout.close()
Yonibear
27-05-2006, 22:22
Ok, das mit dem doppelten Speicherverbrauch ist ein Argument.
Mich hat jetzt vor allem interessiert, ob es irgendeine elegantere Lösung dafür gibt, als auf irgendeine Art C-Code zu erzeugen, aber anscheinend ist das ja nicht so einfach.
richtig statisch wirst es nich hinbekommen, mac ht auch ned viel sinn imho.
Weil wenn sich Deine daten aendern, musst du deine exe/dll oder wo auch immer du die daten haelst, neu linken.
Das compileieren linken iss meist ned das problem, aber das neu verteilen dann.
Das naechste Problem ist die groesse der daten.
das Datensegment (wo die "einkompilierten" constanten daten liegen) iss unter windows immer noch begrenzt. mittlerweile grosszuegiger als noch unter w95, aber trotzdem begrenzt.
Ne "elegante" loesung um grosse dateien unuebersetzt und unangetastet in den speicher zu bekommen, wo dann sogar mit dateioperationen direkt auf dem Hauptspeicher arbeiten kannst, ist memory mapped IO. (da wird ne datei einfach in den speicher gemappt)
Das ist unter allen BS sogar recht performant implementiert, da es grundlage fast aller hoeheren dateioperationen ist.
Ciao ...
richtig statisch wirst es nich hinbekommen, mac ht auch ned viel sinn imho.
Weil wenn sich Deine daten aendern, musst du deine exe/dll oder wo auch immer du die daten haelst, neu linken.
Das compileieren linken iss meist ned das problem, aber das neu verteilen dann.
Das naechste Problem ist die groesse der daten.
das Datensegment (wo die "einkompilierten" constanten daten liegen) iss unter windows immer noch begrenzt. mittlerweile grosszuegiger als noch unter w95, aber trotzdem begrenzt.
Ne "elegante" loesung um grosse dateien unuebersetzt und unangetastet in den speicher zu bekommen, wo dann sogar mit dateioperationen direkt auf dem Hauptspeicher arbeiten kannst, ist memory mapped IO. (da wird ne datei einfach in den speicher gemappt)
Das ist unter allen BS sogar recht performant implementiert, da es grundlage fast aller hoeheren dateioperationen ist.
Ciao ...
Siehe dazu man mmap (http://unixhelp.ed.ac.uk/CGI/man-cgi?mmap).
Yonibear
29-05-2006, 14:26
Darum gings mir weniger, ich entwickel was für den GP2X, da ist Linux drauf, was mit den großen Datensegmenten ja keine Probleme haben sollte. Es wäre halt einfach handlicher, eine von Daten unabhängige Datei zu haben, aber das scheint ja nicht ohne so zu gehen, wie ich mir das vorgestellt habe.
Beispiel:
Datei Blabla.txt:
Dies ist Blabla
Datei test.c:
#include <stdio.h>
extern char _binary_Blabla_txt_begin[];
extern char _binary_Blabla_txt_size; // ACHTUNG! Nur mittels Referenz zugreifen!
int main()
{
for(i=0; i<(int) &_binary_Blabla_txt_size; i++) {
putchar(_binary_Blabla_txt_start[i]);
}
}
Und nun das Objekt erzeugen:
$ objcopy -I binary -O elf32-i386 -B i386 Blabla.txt blabla.oDann normal dazulinken:
$ gcc test.c blabla.o -o tollesosseUnd testen:
$ ./tollesosse
Dies ist Blabla
Wenn die Datei foobar.xyz heißt, heißen die Symbole natürlich _binary_foobar_xyz_begin etc. So kannst du beliebig viele Dateien mit einlinken.
HTH
wäre halt einfach handlicher, eine von Daten unabhängige Datei zu haben
Naja, die entwicklung in der SW Branche geht genau in die andere richtung (Modularitaet),
aber eine "Alles in einer datei" Loesung hat fuer den User immernoch nicht zu unterschaetzenden Reiz.
BTW die max groesse eines constanten Char Arrays iss ned definiert, also koentest wie Joghurt vorschlaegt, nen riesen char block global anlegen ...
extern char binary_Blabla_txt[];
fuer die compatiblitaet mit anderen binary formaten wuerd ich da keine daten per textdatei zulinken, sondern die daten herkoemmlich in ner .c oder .cpp datei anlegen ....
binary_Blabla_txt.cpp:
char binary_Blabla_txt[] = {"Dies ist Blabla"}; // fuer die Textversion ^^
char binary_Blabla_txt[] = {123,234,232}; // fuer die binaere version
zum erzeugen der cpp kann man sich dann natuerlich nen script / programm schreiben, welches einem die datei generiert ...
Unter windows btw kann man alles linken was einem unter den nagel kommt, weiss nicht ob das das selbe ist was Joguhrt mit den objcopy macht ... dazu kenn ich mich mit den linux binaries zu wenig aus. windows hat zum glueck nur 1 binaeres format ^^
wichtig iss halt nur zu wissen wie die daten aufgebaut sind ....
@Joguhrt
wie verlinkt er eigentlich dein char _binary_Blabla_txt_begin symbol, mit dem begin des Datensegments, wo deine zugelinktes objectfile beginnt ? kann der linker das so einfach ?
Ciao ...
Yonibear
30-05-2006, 14:23
@ Joghurt:
Danke! Das war genau das was ich wissen wollte.
Klar kann ich auch sonstwie C-Code generieren, es hat mich jetzt aber einfach mal interessiert ob es auch praktischer geht.
Bei GP2X-Spielen zb. ist es einfach praktischer und man kan sich Modularität sparen, eher ist es sinnvoll die Daten auf diese Weise zu verstecken, damit ein Anreiz besteht, sich Extras freizuspielen.
eher ist es sinnvoll die Daten auf diese Weise zu verstecken
die daten wenn die so zulinkst, sind fuer den user, der 3+3 zusammenzaehlen kann und nen hexeditor bedienen kann, im klartetxt lesbar und manipulierbar. also verlass dich da ned drauf ^^
Quasi alles was im datensegment steht, iss durch ne manipulation des binaries veraenderbar, das binaerformat iss ja auch hinreichend gut dokumentiert ^^
Ciao ...
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.