Соображения языка C++
Поскольку Ваш драйвер будет, вероятно, записан как комбинация C и кода C++, существуют некоторые потенциальные ловушки, которых необходимо попытаться избежать. Многие из них описаны в этой главе.
Набор I/O в целом записан в подмножестве C++. Следующие функции не позволяются:
исключения
шаблоны
множественное наследование
нетривиальные конструкторы
(в выделении памяти и подобный нужно выполнить
init
функция)стандартная динамическая идентификация типов (RTTI)
(Подобная RTTI функциональность обеспечила OSDynamicCast),
списки инициализации
Для получения дополнительной информации см. Основные принципы IOKit и раздел Object Creation и Destruction Руководства по проектированию Драйвера устройства IOKit.
Различия в размере типа данных
Одна из наиболее распространенных ошибок при портировании ядра драйвера C на Набор I/O предполагает, что тип данных в C будет иметь тот же размер как тип данных с аналогичным именем в C++. Это не всегда имеет место.
Хорошее правило состоит в том, чтобы всегда удостоверяться, что Вы используете точно тот же тип данных (с тем же именем) с обеих сторон когда передающие данные между C и частями C++ Вашего драйвера. Это может спасти Вас много головных болей и ненужной отладки в будущем.
Обработка C к обратным вызовам C++
C код не может вызвать методы класса непосредственно. Это излагает что-то вроде проблемы, если Вы пишете код, куда метод C++ должен быть передан как обратный вызов в Ваш базовый код C.
Для обхождения этой проблемы необходимо создать промежуточную функцию ретрансляции в файле C++. Эта функция является стандартом C функция, но скомпилированное использование компилятора C++. Эта функция может тогда быть вызвана функциями C и легко выполнить вызовы в методы класса C++.
Соблюдающие правила должны сопровождаться:
Функция C++ должна быть объявлена
static
.Одним из его параметра должен быть указатель на экземпляр Вашего класса.
Вызовы для классификации функций должны тогда быть выполнены относительно того указателя.
Например, Вы могли бы записать функцию ретрансляции, которая похожа на это:
static int org_mklinux_iokit_swim3_driver_dosomething( |
org_mklinux_iokit_swim3_driver *self, int something_arg) |
{ |
dIOLog(DEBUG_GENERAL, "dosomething: enter (0x%x)\n", |
(unsigned int)self); |
self->dosomething(something_arg); |
} |
Для Вашего обратного вызова необходимо было бы передать две вещи в базовый код C: адрес экземпляра класса (значение this
указатель), и адрес этой функции. После этого код C может вызвать функцию класса dosomething
путем выполнения чего-то вроде этого:
ret = (*funcptr)(classptr, argument); |
где funcptr
указатель на функцию ретрансляции, classptr
указатель на экземпляр класса чей dosomething
метод нужно вызвать, и argument
параметр, который будет передан dosomething
метод.