0

I was having trouble with Ogg Vorbis callbacks not working, specifically the read_func callback, the others all seemed to work. I just made this (in my opinion pointless) change, and suddenly it started working. Does anyone know exactly why, because I am having a hard time seeing the exact difference here. It seems an explicit cast to a function pointer is necessary?

BEFORE (Ogg fails to ever read in valid header data, despite trying):

ov_callbacks oggFileCallbacks;

oggFileCallbacks.read_func = ogg_read_func;
oggFileCallbacks.seek_func = ogg_seek_func;
oggFileCallbacks.tell_func = ogg_tell_func;
oggFileCallbacks.close_func = ogg_close_func;

AFTER (Works perfectly as expected):

ov_callbacks oggFileCallbacks = {
  (size_t (*)(void *, size_t, size_t, void *))  ogg_read_func,
  (int (*)(void *, ogg_int64_t, int))           ogg_seek_func,
  (int (*)(void *))                             ogg_close_func,
  (long (*)(void *))                            ogg_tell_func
};

EDIT: More information

The structure initialization did change when I fixed the problem because it was constructed using the contents in the brackets, but I somehow suspect the real problem was the lack of explicit casting. I thought I had a good knowledge of C++ but I have decided I need to really try to figure out these oddities when I come across them. One thing of note is that my code is in C++, and the Vorbis library is written in plain C. I also decided to force these function pointers to use C prototype declaration style but that did not help the issue either. Structure was initialized like this (for the old way that doesn't work):

 ov_callbacks oggFileCallbacks;

Here is the function definition of ogg_read_func:

size_t ogg_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) {

Here are the prototypes:

// Ogg read functions (mainly useful for android (non standard file io ))
extern "C" {
size_t ogg_read_func(void *ptr, size_t size, size_t nmemb, void *datasource);
int    ogg_seek_func(void *datasource, ogg_int64_t offset, int whence);
int    ogg_close_func(void *datasource);
long   ogg_tell_func(void *datasource);
}

The ogg_read_func was just a wrapper to fread when I was debugging the issue, and despite that before changing the structure initialization and doing the cast the error returned was always "Not ogg vorbis", or in code terms this value:

#define OV_ENOTVORBIS -132

Bakou
  • 1
  • 1
  • 1
    In what way don't they work? How are these functions declared? – Mike Seymour Sep 26 '14 at 18:40
  • What specific failures are you getting? – n. 'pronouns' m. Sep 26 '14 at 18:44
  • 2
    You shouldn't need those casts — it's almost always an error to cast a function. Doesn't it compile without them? – molbdnilo Sep 26 '14 at 19:06
  • I agree, that is why I didn't cast them at first. Yet magically they make the ogg file readable. The way in which they didn't work is hard to determine exactly as the Ogg/Vorbis library is huge and not exactly clearly coded, but to me it basically seemed like it was not finding valid header data and it returned an error saying "This is not an ogg file". It was however still reading in about 10kb of data before failing. – Bakou Sep 26 '14 at 21:27
  • It doesn't work if you assign the pointers, it works if you cast the pointers and initialize the struct. What if you initialize but don't cast? Or if you assign and cast? – Ulrich Eckhardt Sep 26 '14 at 21:37

0 Answers0