mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Added class for catching C++ exceptions. When using libobjc2, you can catch C++ exceptions by writing @catch(CXXException *e). This will wrap the C++ exception in an Objective-C object and allow you to access it by sending a -thrownValue message to the object. This returns a pointer to the exception. For example, if the exception is an integer, you would retrieve it like this from Objective-C:
@catch(CXXException *e) { int i = *(int*)[e thrownValue]; } In ObjC++, you can also make sure that it really is an int, by doing: assert(typeid(int) == *(std::type_info*)[e cxx_type_info]); These interfaces are experimental and subject to change without notice. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@30904 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c7ef614806
commit
edcd8d0c5d
3 changed files with 108 additions and 0 deletions
10
Headers/Additions/GNUstepBase/CXXException.h
Normal file
10
Headers/Additions/GNUstepBase/CXXException.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
struct _Unwind_Exception;
|
||||
@interface CXXException : NSObject
|
||||
{
|
||||
struct _Unwind_Exception *ex;
|
||||
}
|
||||
+ (id)exceptionWithForeignException: (struct _Unwind_Exception*)ex;
|
||||
- (void*)thrownValue;
|
||||
- (void*)cxx_type_info;
|
||||
@end
|
97
Source/CXXException.m
Normal file
97
Source/CXXException.m
Normal file
|
@ -0,0 +1,97 @@
|
|||
#if defined(__has_include) && __has_include(<objc/hooks.h>)
|
||||
#import "Foundation/NSObject.h"
|
||||
#import "Additions/GNUstepBase/CXXException.h"
|
||||
#include <objc/runtime.h>
|
||||
#include <objc/hooks.h>
|
||||
|
||||
/** From the CodeSourcery ABI Spec, with C++ pointers turned to void*, and
|
||||
* other parts abridged. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
_URC_FOREIGN_EXCEPTION_CAUGHT = 1
|
||||
} _Unwind_Reason_Code;
|
||||
|
||||
struct _Unwind_Exception;
|
||||
|
||||
typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
|
||||
struct _Unwind_Exception *);
|
||||
struct _Unwind_Exception
|
||||
{
|
||||
uint64_t exception_class;
|
||||
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
||||
unsigned long private_1;
|
||||
unsigned long private_2;
|
||||
} __attribute__((__aligned__));
|
||||
|
||||
_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *);
|
||||
|
||||
|
||||
struct __cxa_exception
|
||||
{
|
||||
void* exceptionType;
|
||||
void (*exceptionDestructor) (void *);
|
||||
void (*unexpectedHandler) (void *);
|
||||
void (*terminateHandler) (void *);
|
||||
void * nextException;
|
||||
|
||||
int handlerCount;
|
||||
int handlerSwitchValue;
|
||||
const char * actionRecord;
|
||||
const char * languageSpecificData;
|
||||
void * catchTemp;
|
||||
void * adjustedPtr;
|
||||
|
||||
struct _Unwind_Exception unwindHeader;
|
||||
};
|
||||
|
||||
@implementation CXXException
|
||||
static Class CXXExceptionClass;
|
||||
// TODO: Add an API for registering other classes for other exception types
|
||||
static Class boxClass(int64_t foo)
|
||||
{
|
||||
if (foo == *(int64_t*)"GNUCC++\0")
|
||||
{
|
||||
return CXXExceptionClass;
|
||||
}
|
||||
return Nil;
|
||||
}
|
||||
+ (void)load
|
||||
{
|
||||
CXXExceptionClass = self;
|
||||
_objc_class_for_boxing_foreign_exception = boxClass;
|
||||
}
|
||||
+ (id)exceptionWithForeignException: (struct _Unwind_Exception*)ex
|
||||
{
|
||||
CXXException *box = [self new];
|
||||
box->ex = ex;
|
||||
return [box autorelease];
|
||||
}
|
||||
- (void*)thrownValue
|
||||
{
|
||||
return ex+1;
|
||||
}
|
||||
- (void*)cxx_type_info
|
||||
{
|
||||
char *ptr = (char*)ex;
|
||||
ptr -= __builtin_offsetof(struct __cxa_exception, unwindHeader);
|
||||
return ((struct __cxa_exception*)ptr)->exceptionType;
|
||||
}
|
||||
- (void)rethrow
|
||||
{
|
||||
struct _Unwind_Exception *re = ex;
|
||||
// We aren't allowed to hold onto the exception if it's been rethrown.
|
||||
ex = 0;
|
||||
_Unwind_Resume_or_Rethrow(re);
|
||||
}
|
||||
- (void)dealloc
|
||||
{
|
||||
if (0 != ex && 0 != ex->exception_cleanup)
|
||||
{
|
||||
ex->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, ex);
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
|
||||
#endif
|
|
@ -146,6 +146,7 @@ GNU_HEADERS = $(ADD_HEADERS)
|
|||
# GNUStep source files
|
||||
|
||||
BASE_MFILES = \
|
||||
CXXException.m\
|
||||
GSArray.m \
|
||||
GSAttributedString.m \
|
||||
GSConcreteValue.m \
|
||||
|
|
Loading…
Reference in a new issue