Use Fmodex callback under C++

421 views Asked by At

i'm using fmodex and i'm trying to use FMOD_FILE_OPEN_CALLBACK under C++.

FMOD_RESULT F_CALLBACK FMOD_FILE_OPEN_CALLBACK(const char *name, unsigned int *filesize, void **handle, void *userdata);

But I would like to execute a method of a class. So I thought to pass current object this as userdata of the callback and execute my callback method as it's proposed here. But unlike Fmod Studio, there is no fileuserdata in FMOD_CREATESOUNDEXINFO, only userdata pointer.

And documentation says :

[w] Optional. Specify 0 to ignore. This is user data to be attached to the sound during creation. Access via Sound::getUserData. Note: This is not passed to FMOD_FILE_OPENCALLBACK, that is a different userdata that is file specific.

But how can I access this file specific pointer ? Or there is an other solution to do that ?

Thanks.

2

There are 2 answers

1
Cheers and hth. - Alf On

When the API in question does not provide a user data pointer for the callback, but does provide some kind of handle, as seems to be the case here, then you can forward each callback call to a C++ method (a non-static member function) in two general ways + 1 API-specific way:

  • use API functionality to associate a C++ object pointer with each handle, or

  • use a static storage std::map or std::unordered_map that associates each handle with a C++ object pointer, or

  • use a dynamically created trampoline function with the object address hardwired.

The third option was used e.g. in Borland's ObjectWindows framework in the 1990's, and it's generally the fastest, but it conflicts with current malware protection schemes, and since the C++ standard library doesn't support it (and as far as I know Boost doesn't support it either, although The Good Puppy over in the C++ Lounge here at SO once made a proposal about it), it's necessarily platform specific machine code.

Thus, if you don't know a way to do the first option I suggest you go with the second, a std::map or std::unordered_map that associates handles with C++ objects.

The main remaining technical hurdle is then to decide the proper time to create a map entry, and the proper time to remove it. That is highly dependent on the callback scheme. And unfortunately I have zero experience with yours, but maybe others can chime in about that detail.

3
Jop On

was this solved yet? If not here's how i do it.

FMOD_CREATESOUNDEXINFO* info = new FMOD_CREATESOUNDEXINFO();
info->cbsize = sizeof(FMOD_CREATESOUNDEXINFO);

// This is the field you want to set
info->fileuserdata = someUserData;

_system->createStream(file.c_str(), FMOD_DEFAULT, info, &_currentSound);

Are you using an old version of the fmod library? On my system the fileuserdata field does exist. I'm using the fmodex low level api that shipped with the fmod studio installation.