[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libcdio-devel] RFC: C++ wrapper exception handling
From: |
R. Bernstein |
Subject: |
[Libcdio-devel] RFC: C++ wrapper exception handling |
Date: |
Sun, 15 Jan 2006 06:26:29 -0500 |
I've been working a little on wrapping libcdio for Python using SWIG
and one of the things I realized in the OO C++ wrapper was that
perhaps it would be more C++ idiomatic to raise exceptions on device
errors rather than give the status as a function return.
So as a test, I've converted all of the routines in cdio++/device.hpp
to throw an error. This test is in CVS and if folks want to give
comments on it -- (e.g. in favor of this approach or not?) -- I'd be
grateful. Lacking other guidance, I'll probably then convert the other
C++ routines that return driver_return_code_t into throwing
exceptions.
Here's the relevant portion of the code:
include/cdio++/cdio.hpp:
class CdioDevice
{
...
class DriverOpException
{
public:
driver_return_code_t driver_return_code;
DriverOpException( driver_return_code_t drc ) {
driver_return_code = drc;
};
driver_return_code_t get_code(void) {
return driver_return_code;
};
const char *get_msg(void) {
return cdio_driver_return_code_to_str(driver_return_code);
};
};
...
private:
void throw_device_exception(driver_return_code_t drc)
{
if (DRIVER_OP_SUCCESS == drc) return;
throw DriverOpException(drc);
}
};
include/cdio++/device.hpp:
...
void closeTray (const char *psz_drive, /*in/out*/ driver_id_t &driver_id)
{
driver_return_code_t drc = cdio_close_tray (psz_drive, &driver_id);
throw_device_exception(drc);
}
...
C++/OO/eject.cpp:
...
try {
device.ejectMedia(psz_drive);
printf("CD in CD-ROM drive %s ejected.\n", psz_drive);
}
catch ( CdioDevice::DriverOpException e ) {
printf("Ejecting CD from CD-ROM drive %s operation error:\n\t%s.\n",
psz_drive, e.get_msg());
}
...
Stroustrup's C++ Programming Language book suggests subclassing
exceptions, perhaps like this:
cdio.hpp:
class DriverOpException
{
public:
driver_return_code_t driver_return_code;
DriverOpException( void ) {};
DriverOpException( driver_return_code_t drc )
...
};
class DriverOpUnsupported: public DriverOpException {};
// other DriverOp... exceptions
...
void throw_device_exception(driver_return_code_t drc)
{
switch (drc) {
case DRIVER_OP_SUCCESS:
return;
case DRIVER_OP_UNSUPPORTED:
throw DriverOpUnsupported();
// cases for other exceptions...
default:
throw DriverOpException(drc);
}
eject.cpp:
...
try {
device.ejectMedia(psz_drive);
printf("CD in CD-ROM drive %s ejected.\n", psz_drive);
}
catch ( CdioDevice::DriverOpUnsupported e ) {
printf("Ejecting CD from CD-ROM drive %s is unsupported on that device.\n",
psz_drive);
}
catch ( CdioDevice::DriverOpException e ) {
printf("Ejecting CD from CD-ROM drive %s operation error:\n\t%s.\n",
psz_drive, e.get_msg());
}
The asserted benefit is that testing for a particular exception is one
via the "catch" rather than having another test inside the "catch"
using say get_code(). A downside looks like that every time an error
condition is changed that has to be reflected in this
subclassing. Also in the way that I've written this above either
driver_return_code_t will be set or not depending on the throw. No
doubt there's a way to fix this, but some simple attempts failed and I
find myself duplicating more and more code which doesn't seems good
for maintenance.
If however those devout C++ programmers find this (or something else)
better, I'll put it in.
Thanks.
- [Libcdio-devel] RFC: C++ wrapper exception handling,
R. Bernstein <=