• Liebe User, bitte beachtet folgendes Thema: Was im Forum passiert, bleibt im Forum! Danke!
  • Hallo Gemeinde! Das Problem leidet zurzeit unter technischen Problemen. Wir sind da dran, aber das Zeitkontingent ist begrenzt. In der Zwischenzeit dürfte den meisten aufgefallen sein, dass das Erstellen von Posts funktioniert, auch wenn das Forum erstmal eine Fehlermeldung wirft. Um unseren Löschaufwand zu minimieren, bitten wir euch darum, nicht mehrmals auf 'Post Reply' zu klicken, da das zur Mehrfachposts führt. Grußworte.

Frage an die C++-Profis (STL)

Mitglied seit
04.08.2002
Beiträge
1.869
Reaktionen
0
Moin.

Hiermit oute ich mich ganz offiziell als Anfänger in Sachen STL ;)

Es geht darum, dass ich einen Dateizugriff, den ich bisher mit fread, fseek und ftell gemacht habe, gerne für ein C++ Programm mit io-streams realisieren möchte.

Die alten Funktionen sehen wie folgt aus:


size_t ov_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
{
return fread(ptr, size, nmemb, (FILE*)datasource);
}

int ov_seek_func(void *datasource, ogg_int64_t offset, int whence)
{
return fseek((FILE*)datasource, (long)offset, whence);
}

long ov_tell_func(void *datasource)
{
return ftell((FILE*)datasource);
}


Mein Ansatz, um das ganze mit einem istream zu machen, sieht folgendermaßen aus:


size_t readDataFromStream(void *ptr, size_t size, size_t nmemb, void *datasource)
{
return ((std::istream*) datasource)->readsome((char*)ptr, nmemb);
}

int seekStreamPosition(void *datasource, ogg_int64_t offset, int whence)
{
//move to the specified initial position
((std::istream*) datasource)->seekg(whence, std::ios::beg);
//move to the specified offset which is relative to the initial position
((std::istream*) datasource)->seekg(offset, std::ios::cur);
return 0;
}

long tellStreamPosition(void *datasource)
{
return ((std::istream*) datasource)->tellg();
}


Hierbei habe ich jetzt direkt mehrere Probleme:

(i) Zum einen klappt die tellStreamPosition() nicht, denn tellg gibt nicht einfach nur einen long-Wert als Positionsangabe zurück sondern ein streampos Objekt. Jetzt ist natürlich die Frage: Wie bekomme ich aus dem streampos Objekt die aktuelle Position (äquivalent zur Rückgabe von ftell)?

(ii) seekStreamPosition() scheint auch nicht korrekt zu funktionieren. Entweder mache ich da einen Denkfehler, oder irgendwas anderes läuft noch schief. Jedenfalls setzt er den Zeiger innerhalb des Streams nicht an die Position, an der er eigentlich sein müsste. Hier habe ich das gleiche Problem mit dem Rückgabewert wie unter (i).

(iii) readDataFromStream() - keine Ahnung ob die sauber arbeitet. Er liest auf jeden Fall Daten aus dem Stream ein und kann die nachher auch sauber verarbeiten, allerdings sind es die Daten von der falschen Position. Ich vermute daher den Fehler nicht in dieser Methode sondern in den beiden anderen.

Falls sich einer der hiesigen C++ Profis erbarmen würde, und mir ein paar Tipps geben könnte, wäre ich echt dankbar.

Thx
m.a.k.

P.S.: gehört zwar nur am Rande zum Thema, aber ich muss mir dringend ein gutes Buch über die STL kaufen. Hat da jemand eine Empfehlung?
 
Mitglied seit
21.07.2002
Beiträge
545
Reaktionen
0
1. WARUM ?! Wenn du funktionierenden C-Code hast, warum wurschtelst du dann irgendwie C++ rein ? ;) Zumal du ja anscheinend nichtmal die Interfaces irgendwie änderst, immernoch void pointer als parameter verwendest C-Casts und überhaupt sieht das ganze nachher deutlich komplizierter aus als vorher und bringt IMO auch keinerlei Vorteile.

2.
(i) sollte einfach funktionieren, streampos implementiert einen operator streamoff, was auch nur ein long typedef ist (zumindest in der Microsoft-Welt ;) ).
(ii) sollte auch so funktionieren. Wenn du weiter mit nem int als rückgabe arbeiten musst dann nimm return ((std::istream*) datasource)->fail()?-1:0;
(iii) readsome arbeitet angeblich nicht korrekt mit filestreams zusammen. Keine Ahnung mit welchen Auswirkungen... :/

Hast du noch nen Beispiel wie du den Stream öffnest und deine Funktionen aufrufst ? Oder kannst du das Problem noch genauer beschreiben ? "Funktioniert nicht richtig" ist immer etwas problematisch.

3. Josuttis' "The C++ Standard Library: A Tutorial and Reference" ist wohl so das Standardwerk der SC++L/STL-Bücher, selbst "gelesen" hab ichs aber nicht. Bin bis jetzt ohne Bücher dazu zurecht gekommen.
 
Mitglied seit
04.08.2002
Beiträge
1.869
Reaktionen
0
Original geschrieben von Invincible[UFF]
1. WARUM ?! Wenn du funktionierenden C-Code hast, warum wurschtelst du dann irgendwie C++ rein ?

die Frage ist recht schnell beantwortet ;):

der code ist teil unseres ogg-vorbis-decoders zum laden und dekodieren von soundfiles für unsere 3d engine.

allerdings basteln wir gerade an einer neuen engine, die komplett in c++ geschrieben werden soll. wir haben eigene archiv-dateien (sowas wie die .pak-files von ID) die wir mittels iostream-routinen auslesen und verarbeiten. und deshalb muss an dieser stelle leider das alte FILE handle raus und ein istream rein.

Original geschrieben von Invincible[UFF]
2.[...]

super danke! heute abend schaff ich das nicht mehr, aber morgen früh guck ich mir das direkt mal an!

Original geschrieben von Invincible[UFF]
Hast du noch nen Beispiel wie du den Stream öffnest und deine Funktionen aufrufst ? Oder kannst du das Problem noch genauer beschreiben ? "Funktioniert nicht richtig" ist immer etwas problematisch.

der stream wird vom globalen resource manager folgendermaßen geöffnet:

std::ifstream *pFileStream = new std::ifstream();
pFileStream->open(strResourceName.c_str(), std::ios::in | std::ios::binary);


anschließend wird ein pointer auf den stream dem ogg-vorbis loader übergeben und der nutzt dann die oben angegebenen callback funktionen um aus dem stream die daten zu lesen bzw. darin zu navigieren.

das problem ist, dass die ersten paar sekunden des sound-files scheinbar nicht geladen werden und der sound daher erst ab der hälfte abgespielt wird.
ich werde morgen deine tipps implementieren und mir dann das problem nochmal genauer anschauen...

Original geschrieben von Invincible[UFF]
3. Josuttis' "The C++ Standard Library: A Tutorial and Reference" ist wohl so das Standardwerk der SC++L/STL-Bücher, selbst "gelesen" hab ichs aber nicht. Bin bis jetzt ohne Bücher dazu zurecht gekommen.

danke für den tipp. da werd ich bezeiten mal einen blick drauf werfen, wenn ich das nächste mal im sternverlag bin.
ich hab mich bisher auch ausschließlich mit online-doku über wasser gehalten, aber die ist leider imho sehr dürftig (oder ich schau einfach auf den falschen seiten nach ^^)
 
Mitglied seit
04.08.2002
Beiträge
1.869
Reaktionen
0
so, hab's hinbekommen. es waren gleich mehrere fehler drin. so schauen die funktionen aus, wenn sie funktionieren ;)


size_t readDataFromStream(void* ptr, size_t size, size_t nmemb, void* datasource)
{
((std::istream*)datasource)->read((char*)ptr, size * nmemb);

//clear all error bits in case we reached the end of file
((std::istream*)datasource)->clear();

return (long)((std::streamoff)((std::istream*)datasource)->gcount());
}

int seekStreamPosition(void* datasource, ogg_int64_t offset, int whence)
{
//move to the specified offset which is relative to the given position
if(whence == SEEK_SET)
((std::istream*) datasource)->seekg(offset, std::ios::beg);
else if(whence == SEEK_CUR)
((std::istream*) datasource)->seekg(offset, std::ios::cur);
else if(whence == SEEK_END)
((std::istream*) datasource)->seekg(offset, std::ios::end);
else
return -1;

//check if movement was successful
if((((std::istream*)datasource)->eof()) || (((std::istream*)datasource)->fail()))
{
//clear error bits
((std::istream*)datasource)->clear();
return -1;
}
else
return 0;
}

long tellStreamPosition(void* datasource)
{
return (long)((std::streamoff)((std::istream*) datasource)->tellg());
}
 
Oben