C++ Language Considerations
Because your driver will probably be written as a combination of C and C++ code, there are some potential pitfalls that you should try to avoid. Many of these are described in this chapter.
The I/O Kit as a whole is written in a subset of C++. The following features are not allowed:
exceptions
templates
multiple inheritance
non-trivial constructors
(memory allocation and similar should be done in the
init
function)standard run-time type identification (RTTI)
(RTTI-like functionality provided with OSDynamicCast)
initialization lists
For more information, see IOKit Fundamentals and the Object Creation and Destruction section of IOKit Device Driver Design Guidelines.
Data Type Size Differences
One of the most common errors when porting a C driver core to the I/O Kit is assuming that a data type in C will have the same size as a data type with a similar name in C++. This is not always the case.
A good rule is to always make sure you use exactly the same data type (with the same name) on both sides when passing data between the C and C++ portions of your driver. This can save you lots of headaches and unnecessary debugging in the future.
Handling C to C++ Callbacks
C code cannot call class methods directly. This poses a bit of a problem if you are writing code where a C++ method needs to be passed as a callback into your C core code.
To get around this issue, you should create an intermediate relay function within a C++ file. This function is a standard C function, but compiled using the C++ compiler. This function can then be called by C functions and easily make calls into C++ class methods.
The following rules must be followed:
The C++ function must be declared
static
.One of its argument must be a pointer to an instance of your class.
Calls to class functions must then be made with respect to that pointer.
For example, you might write a relay function that looks like this:
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); |
} |
For your callback, you would need to pass two things into the C core code: the address of the class instance (the value of the this
pointer), and the address of this function. After that, the C code can call the class function dosomething
by doing something like this:
ret = (*funcptr)(classptr, argument); |
where funcptr
is a pointer to the relay function, classptr
is a pointer to the class instance whose dosomething
method is to be called, and argument
is the argument to be passed to the dosomething
method.
Copyright © 2004, 2009 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2009-05-06