использовать объектно-ориентированные объекты

0

Я использую lib, написанный на C, который позволяет мне читать и писать midi файлы. Хотя я нашел другую библиотеку, написанную в C++, которая работает для меня, я все еще борется с фактом: как я мог использовать C lib с объектами/классами. В lib есть вызов, который перебирает путь к midi файлу, а затем некоторые указатели на функции, вызываемые для определенных типов midi-event. Итак, это будет выглядеть так (аннотация):

int main( int argc, char** args )
{
    readMidi( args[ 1 ], onMidiEvent, onSysEvent, onError, ... );
}

Я попытался использовать указатель на экземпляр класса, который собирает воспроизводимые ноты:

class MidiNoteList;

template < MidiNoteList* VMidi > onError( short errmsg, char* msg ) { ... }
...

int main( int argc, char** args )
{
    MidiNoteList* m( new MidiNoteList( ) );
    readMidi( args[ 1 ], onMidiEvent< m >, onSysEvent< m >, onError< m >, ... );
}

GCC говорит, что m не может использоваться как постоянное выражение. Я понимаю, что m должен быть постоянным во время компиляции, поэтому я уверен, почему я не могу сделать это так. Но как я могу решить эту "проблему" по-другому?

Теги:
templates
gcc
function-pointers

1 ответ

3
Лучший ответ

Обычно такие библиотеки используют дополнительный аргумент void * который передается функции, которая принимает указатели на функции, и возвращается обратно ко всем функциям обратного вызова. Если у вас есть это, вы можете использовать его для передачи указателя объекта, отбрасывая его на пустое и обратно:

class MyObject;
void errCallback(void *m, short errcode, char *errmsg) {
    static_cast<MyObject *>(m)->error(errcode, errmsg);
}

    :
    MyObject *m = new MyObject();
    callLibrary(..., errCallback, m, ...);

Если библиотека не дает вам дополнительный аргумент, у вас есть проблема - единственный способ получить дополнительные данные в функции обратного вызова - использовать глобальную переменную:

static MyObject *m;
void errCallback(short errcode, char *errmsg) {
    m->error(errcode, errmsg);
}
    :
    m = new MyObject();
    callLibrary(..., errCallback, ...);

Проблема состоит в том, что вам нужно объявить новую функцию обратного вызова (и глобальную переменную) для каждого отдельного объекта, для которого вы хотите получать обратные вызовы. Если вы создаете много таких объектов динамически, это становится громоздким для управления.

  • 0
    Первый не подходит для меня, потому что, как вы и ожидали для варианта 2, переменная void * отсутствует. Таким образом, единственный оставшийся вариант - ваш второй. Я тоже это имел в виду, но это не похоже на использование объекта.
  • 0
    @JoshuaBehrens: вы можете инкапсулировать глобальную переменную var и функцию как статические члены MyObject если хотите - все еще не «объектно-ориентированные», но тогда OO - это не серебряная пуля, которая решает все проблемы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню