summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Jezabek <jezabek@poczta.onet.pl>2008-08-28 20:39:17 +0000
committerJan Jezabek <jezabek@poczta.onet.pl>2008-08-28 20:39:17 +0000
commit12bfa282fcf60b9fe07931b8ea83c6d21d69d970 (patch)
treee0f20984109946e5544205e75a217db2d87b9d1f
parent7b97de43ba87f8b29c4861c2769cbeab95c002e7 (diff)
downloadswig-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.c83
-rw-r--r--Examples/test-suite/com/virtual_poly_runme.c2
-rw-r--r--Lib/com/com.swg67
-rw-r--r--Source/Modules/com.cxx10
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"