diff options
author | Jan Jezabek <jezabek@poczta.onet.pl> | 2008-08-28 20:39:17 +0000 |
---|---|---|
committer | Jan Jezabek <jezabek@poczta.onet.pl> | 2008-08-28 20:39:17 +0000 |
commit | 12bfa282fcf60b9fe07931b8ea83c6d21d69d970 (patch) | |
tree | e0f20984109946e5544205e75a217db2d87b9d1f | |
parent | 7b97de43ba87f8b29c4861c2769cbeab95c002e7 (diff) | |
download | swig-12bfa282fcf60b9fe07931b8ea83c6d21d69d970.tar.gz |
Added better support for exceptions - now a description is added. Added corresponding run-test. Fixed a serious typo in the deallocation code for the module class.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-jezabek@10798 626c5289-ae23-0410-ae9c-e8d60b6d4f22
-rw-r--r-- | Examples/test-suite/com/throw_exception_runme.c | 83 | ||||
-rw-r--r-- | Examples/test-suite/com/virtual_poly_runme.c | 2 | ||||
-rw-r--r-- | Lib/com/com.swg | 67 | ||||
-rw-r--r-- | Source/Modules/com.cxx | 10 |
4 files changed, 159 insertions, 3 deletions
diff --git a/Examples/test-suite/com/throw_exception_runme.c b/Examples/test-suite/com/throw_exception_runme.c new file mode 100644 index 000000000..d701e4b76 --- /dev/null +++ b/Examples/test-suite/com/throw_exception_runme.c @@ -0,0 +1,83 @@ +#define CINTERFACE +#include <stdio.h> +#include <windows.h> + +#ifndef MSVC +/* This is a workaround for a VC specific attribute */ +#define __RPC__deref_out +#endif + +#ifdef __DMC__ +#define __RPCNDR_H_VERSION__ ( 450 ) +#endif + +#include "throw_exception/throw_exception_generated.h" + +void check_message(wchar_t *expected_msg) { + IErrorInfo *iei = NULL; + wchar_t *descr = NULL; + + GetErrorInfo(0, &iei); + + iei->lpVtbl->GetDescription(iei, &descr); + iei->lpVtbl->Release(iei); + + if (wcscmp(expected_msg, descr)) { + fprintf(stderr, "Incorrect message description\n"); + exit(1); + } + + /* Should we release descr? */ + CoTaskMemFree(descr - 2); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + Ithrow_exception *te = NULL; + IFooStatic *fs = NULL; + IFoo *foo = NULL; + IErrorInfo *iei = NULL; + HRESULT hres; + + CoInitialize(NULL); + + CoCreateInstance(&CLSID_throw_exceptionImpl, NULL, CLSCTX_INPROC_SERVER, &IID_Ithrow_exception, (void **) &te); + + /* Construct Foo object */ + te->lpVtbl->get_Foo(te, &fs); + fs->lpVtbl->new_Foo(fs, &foo); + + hres = foo->lpVtbl->test_int(foo); + + if (hres != E_ABORT) { + fprintf(stderr, "Exception should have been thrown\n"); + exit(1); + } + + check_message(L"C++ int exception thrown"); + + hres = foo->lpVtbl->test_msg(foo); + + if (hres != E_ABORT) { + fprintf(stderr, "Exception should have been thrown\n"); + exit(1); + } + + check_message(L"C++ char const * exception thrown"); + + hres = foo->lpVtbl->test_cls(foo); + + if (hres != E_ABORT) { + fprintf(stderr, "Exception should have been thrown\n"); + exit(1); + } + + check_message(L"C++ Error exception thrown"); + + foo->lpVtbl->Release(foo); + fs->lpVtbl->Release(fs); + te->lpVtbl->Release(te); + + CoUninitialize(); + + return 0; +} diff --git a/Examples/test-suite/com/virtual_poly_runme.c b/Examples/test-suite/com/virtual_poly_runme.c index 7808d3e41..ee6b193ea 100644 --- a/Examples/test-suite/com/virtual_poly_runme.c +++ b/Examples/test-suite/com/virtual_poly_runme.c @@ -147,5 +147,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine vp->lpVtbl->Release(vp); + CoUninitialize(); + return 0; } diff --git a/Lib/com/com.swg b/Lib/com/com.swg index e68daf31f..59b0b1917 100644 --- a/Lib/com/com.swg +++ b/Lib/com/com.swg @@ -341,6 +341,7 @@ SWIGTYPE[], SWIGTYPE[ANY] %{ + SWIG_SetErrorInfo(L"C++ $1_type exception thrown", L"", &IID_IUnknown); return $null; %} @@ -376,6 +377,7 @@ typedef struct { SWIG_funcptr *vtable; /* vtable for the methods of the wrapped object */ SWIG_funcptr *SWIGWrappedObject_vtable; /* vtable for helper methods */ SWIG_funcptr *aggregated_vtable; /* vtable to present to the outer object */ + SWIG_funcptr *ISupportErrorInfo_vtable; void *cPtr; /* pointer to the wrapped object */ int cMemOwn; /* memory owned by the proxy? */ LONG refCount; /* reference count */ @@ -392,6 +394,31 @@ static int SWIGIsEqual(const GUID *a, const GUID *b) { return memcmp(a, b, sizeof(GUID)) == 0; } +void SWIG_SetErrorInfo(const wchar_t *msg, const wchar_t *source, const GUID *guid) { + SWIGIUnknown *icei; + IErrorInfo *iei; + + CreateErrorInfo((ICreateErrorInfo **) &icei); + + /* SetGUID */ + ((HRESULT (SWIGSTDCALL *)(SWIGIUnknown *, const GUID *)) icei->vtable[3])(icei, guid); + + /* SetSource */ + ((HRESULT (SWIGSTDCALL *)(SWIGIUnknown *, LPCOLESTR)) icei->vtable[4])(icei, source); + + /* SetDescription */ + ((HRESULT (SWIGSTDCALL *)(SWIGIUnknown *, LPCOLESTR)) icei->vtable[5])(icei, msg); + + /* Use QueryInterface to convert ICreateErrorInfo to IErrorInfo */ + ((HRESULT (SWIGSTDCALL *)(SWIGIUnknown *, REFGUID, LPVOID *)) icei->vtable[0])(icei, IID_IErrorInfo, (void **) &iei); + + SetErrorInfo(0, iei); + + /* Release both object references */ + ((LONG (SWIGSTDCALL *)(SWIGIUnknown *)) icei->vtable[2])(icei); + ((LONG (SWIGSTDCALL *)(SWIGIUnknown *)) ((SWIGIUnknown *) iei)->vtable[2])((SWIGIUnknown *) iei); +} + long SWIGSTDCALL SWIGAddRef1(void *iunk) { SWIGWrappedObject *obj = (SWIGWrappedObject *) iunk; @@ -414,6 +441,10 @@ long SWIGSTDCALL SWIGAddRef3(void *iunk) { return InterlockedIncrement(&obj->refCount); } +long SWIGSTDCALL SWIGAddRef4(void *iunk) { + return SWIGAddRef1((void **)iunk - 3); +} + long SWIGSTDCALL SWIGRelease1(void *iunk) { SWIGWrappedObject *obj = (SWIGWrappedObject *) iunk; @@ -464,6 +495,22 @@ long SWIGSTDCALL SWIGRelease3(void *iunk) { return res; } +long SWIGSTDCALL SWIGRelease4(void *iunk) { + return SWIGRelease1((void **)iunk - 3); +} + +HRESULT SWIGSTDCALL SWIGQueryInterface4(void *iunk, GUID *iid, void **ppvObject) { + /* + * Forwards the call to the main vtable. This is not optimal as the call cannot + * be inlined. However generating a separate function for each class is + * rather inconvenient. + */ + + SWIGWrappedObject *obj = (SWIGWrappedObject *) ((void **) iunk - 3); + + return ((HRESULT (SWIGSTDCALL *)(void *, GUID *, void **)) obj->vtable[0]) ((void *) obj, iid, ppvObject); +} + void * SWIGSTDCALL SWIGGetCPtr(void *iunk) { SWIGWrappedObject *obj = (SWIGWrappedObject *) ((void **)iunk - 1); @@ -500,6 +547,17 @@ HRESULT SWIGSTDCALL SWIGInvoke(SWIGWrappedObject *obj, DISPID dispIdMember, REFI return hres; } +HRESULT SWIGSTDCALL SWIGInterfaceSupportsErrorInfo(void *ignored, GUID *riid) { + return S_OK; +} + +SWIG_funcptr ISupportErrorInfo_vtable[] = { + (SWIG_funcptr) SWIGQueryInterface4, + (SWIG_funcptr) SWIGAddRef4, + (SWIG_funcptr) SWIGRelease4, + (SWIG_funcptr) SWIGInterfaceSupportsErrorInfo +}; + static OLECHAR SWIG_typelib_path[MAX_PATH + 1]; static ITypeLib *SWIG_typelib = NULL; @@ -593,7 +651,7 @@ typedef struct { } SWIGClassDescription_t; void _wrap_delete_staticclass(void *arg) { - SWIGWrappedObject *obj = (SWIGWrappedObject *) obj; + SWIGWrappedObject *obj = (SWIGWrappedObject *) arg; #ifdef __cplusplus delete obj; #else @@ -609,6 +667,7 @@ void *_wrap_new_staticclass(SWIG_funcptr *vtable, GUID *iid) { #endif res->vtable = vtable; res->SWIGWrappedObject_vtable = NULL; + res->ISupportErrorInfo_vtable = ISupportErrorInfo_vtable; /* cPtr and cMemOwn make no sense for static classes */ res->cPtr = NULL; res->cMemOwn = 0; @@ -628,10 +687,13 @@ HRESULT SWIGSTDCALL _wrap_staticclass_QueryInterface(void *that, GUID *iid, void if (SWIGIsEqual(iid, &IID_IUnknown) || SWIGIsEqual(iid, &IID_IDispatch) || (obj->additionalIID != NULL && SWIGIsEqual(iid, obj->additionalIID))) { - /* FIXME: This could be more elegant */ SWIGAddRef1(that); *ppvObject = that; return S_OK; + } else if (SWIGIsEqual(iid, &IID_ISupportErrorInfo)) { + SWIGAddRef1(that); + *ppvObject = &obj->ISupportErrorInfo_vtable; + return S_OK; } return E_NOINTERFACE; @@ -680,6 +742,7 @@ void * SWIGSTDCALL SWIG_wrap_opaque(void *arg, int cMemOwn) { #endif res->vtable = _wrap_opaque_vtable; res->SWIGWrappedObject_vtable = _wrap_opaque_SWIGWrappedObject_vtable; + res->ISupportErrorInfo_vtable = ISupportErrorInfo_vtable; res->cPtr = arg; res->cMemOwn = cMemOwn; InterlockedIncrement(&globalRefCount); diff --git a/Source/Modules/com.cxx b/Source/Modules/com.cxx index aaba8141a..c454f0a0e 100644 --- a/Source/Modules/com.cxx +++ b/Source/Modules/com.cxx @@ -1435,6 +1435,10 @@ public: " SWIGAddRef1(that);\n" " *ppvObject = &obj->SWIGWrappedObject_vtable;\n" " return S_OK;\n" + " } else if (SWIGIsEqual(iid, &IID_ISupportErrorInfo)) {\n" + " SWIGAddRef1(that);\n" + " *ppvObject = &obj->ISupportErrorInfo_vtable;\n" + " return S_OK;\n" " }\n\n"); Printf(proxy_class_vtable_code, " if (SWIGIsEqual(iid, &IID_IUnknown) ||\n" @@ -1460,7 +1464,6 @@ public: } Printf(proxy_class_vtable_code, ") {\n" - " /* FIXME: This could be more elegant */\n" " SWIGAddRef1(that);\n" " *ppvObject = obj;\n" " return S_OK;\n" @@ -1497,6 +1500,10 @@ public: " SWIGAddRef3(that);\n" " *ppvObject = &obj->SWIGWrappedObject_vtable;\n" " return S_OK;\n" + " } else if (SWIGIsEqual(iid, &IID_ISupportErrorInfo)) {\n" + " SWIGAddRef1(that);\n" + " *ppvObject = &obj->ISupportErrorInfo_vtable;\n" + " return S_OK;\n" " }\n\n"); /* Special case for aggregation - IUnknown has to be different */ @@ -1681,6 +1688,7 @@ public: " res->vtable = _wrap%svtable;\n" " res->SWIGWrappedObject_vtable = _wrap%sSWIGWrappedObject_vtable;\n" " res->aggregated_vtable = _wrap%saggregated_vtable;\n" + " res->ISupportErrorInfo_vtable = ISupportErrorInfo_vtable;\n" " res->cPtr = arg;\n" " res->cMemOwn = cMemOwn;\n" " res->outer = NULL;\n" |