summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Jezabek <jezabek@poczta.onet.pl>2008-08-17 19:10:36 +0000
committerJan Jezabek <jezabek@poczta.onet.pl>2008-08-17 19:10:36 +0000
commit19a532b297e4da1e6ed22d641ac7ce46a4dbfcf5 (patch)
treec6185e1a2bbb06dafdc57b5ec98c0abadb45b964
parent89f04f678347db150272e4fcb52b400063e0a55c (diff)
downloadswig-19a532b297e4da1e6ed22d641ac7ce46a4dbfcf5.tar.gz
More documentation. Better handling of NULL arguments and return values. Minor configure and Makefile tweaks.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-jezabek@10772 626c5289-ae23-0410-ae9c-e8d60b6d4f22
-rw-r--r--Doc/Manual/COM.html145
-rw-r--r--Examples/Makefile.in2
-rw-r--r--Examples/test-suite/com/aggregate_runme.vbs5
-rw-r--r--Lib/com/com.swg12
-rw-r--r--Source/Modules/com.cxx12
-rw-r--r--configure.in2
6 files changed, 136 insertions, 42 deletions
diff --git a/Doc/Manual/COM.html b/Doc/Manual/COM.html
index c48fe36a1..742c467ea 100644
--- a/Doc/Manual/COM.html
+++ b/Doc/Manual/COM.html
@@ -61,7 +61,7 @@
<p>
-This chapter describes SWIG's support of Java.
+This chapter describes SWIG's support of COM.
It covers most SWIG features, but certain low-level details are covered in less depth than in earlier chapters.
</p>
@@ -177,24 +177,14 @@ swig -com -help
</tr>
<tr>
-<td>-nopgcpp</td>
-<td>suppress the premature garbage collection prevention parameter</td>
-</tr>
-
-<tr>
-<td>-noproxy</td>
-<td>generate the low-level functional interface instead of proxy classes </td>
-</tr>
-
-<tr>
-<td>-package &lt;name&gt;</td>
-<td>set name of the Java package to &lt;name&gt;</td>
+<td>-namespace &lt;name&gt;</td>
+<td>set name to be used as prefix of your classes' IDispatch names (e.g. for use with CreateObject in Basic)</td>
</tr>
</table>
<p>
-Their use will become clearer by the time you have finished reading this section on SWIG and Java.
+Their use will become clearer by the time you have finished reading this section on SWIG and COM.
</p>
<H3><a name="compiling_dynamic"></a>17.2.3 Compiling a dynamic module</H3>
@@ -727,21 +717,10 @@ memory when the object is no longer needed, that is when its reference count rea
<p>
-TODO
-</p>
-
-<div class="code">
-<pre>
-example.spam1(null); // Pointer - ok
-example.spam2(null); // Reference - NullPointerException
-example.spam3(null); // Value - NullPointerException
-example.spam4(null); // Array - ok
-</pre>
-</div>
-
-<p>
-For <tt>spam1</tt> and <tt>spam4</tt> above the Java <tt>null</tt> gets translated into a NULL pointer for passing to the C/C++ function.
-The converse also occurs, that is, NULL pointers are translated into <tt>null</tt> Java objects when returned from a C/C++ function.
+Null values may be passed to C/C++ functions when pointer parameters are expected. Also
+if a C/C++ function returns NULL a null return value is returned by the wrapper.
+You should not pass null to functions expecting a reference - in this case the
+function call will fail with an E_INVALIDARG error.
</p>
<H3><a name="overloaded_functions"></a>17.3.10 C++ overloaded functions</H3>
@@ -1222,21 +1201,127 @@ is to be stored.
<H3><a name="com_iswigwrappedobject"></a>17.4.6 ISWIGWrappedObject interface</H3>
+<p>
+Every COM object created by SWIG implements the interface <tt>ISWIGWrappedObject</tt> with
+the interface ID <tt>{1a3a5cc8-9a61-4681-ae9c-d04293f35734}</tt>. This interface has one
+method (apart from the methods present in the <tt>IUnknown</tt> interface):
+</p>
+
+<div class="code">
+<pre>
+void * getCPtr();
+</pre>
+</div>
+
+<p>
+This method is used for accessing the COM object's underlying C/C++ object. The
+<tt>ISWIGWrappedObject</tt> interface may change in any future version of SWIG
+(speaking precisely it may be replaced by another interface with another IID)
+so you should not rely on its presence. However it may be useful for debugging
+purposes.
+</p>
<H3><a name="com_memory"></a>17.4.7 Memory management</H3>
+<p>
+Every COM proxy object keeps a count of references. If this reference count
+reaches 0 then the proxy object is unused and can be deallocated. SWIG takes
+care of allocating and deallocating memory for proxy objects. By default
+the underlying C/C++ object is left intact when the proxy is destroyed. The
+exceptions are when the proxy object has been created using the class factory
+(this includes <tt>CreateObject</tt> in Basic and the <tt>CoCreateInstance</tt>
+Win32 API call), using a constructor from the class object or using a function
+marked as <tt>%newobject</tt>. In these cases the proxy 'owns' the underlying
+C/C++ object which is destroyed together with the proxy. C++ objects are
+deallocated using <tt>delete</tt>; this means that the destructor
+will be called, just as it would be called in C++.
+</p>
<H3><a name="com_memory"></a>17.4.8 Exceptions</H3>
+<p>
+For now if a C++ exception is thrown the function returns with the error
+code <tt>E_ABORT</tt>. The handling of this error code depends on the
+language that you are using. For example VBScript will exit with an error
+by default; if you need to handle errors more gracefully you can use
+code similar to this:
+</p>
+
+<div class="code">
+<pre>
+Rem Prevent aborting the script
+On Error Resume Next
+
+Rem Call method that might throw an exception
+example.callDangerousMethod()
+
+If Err.Number <> 0 Then
+ Rem Handle error
+End If
+</pre>
+</div>
+
+<p>
+You can customize the exception handling process by modifying the
+<tt>throws</tt> typemap.
+</p>
<H2><a name="com_customization"></a>17.5 Customization features</H2>
<H3><a name="com_typemaps"></a>17.5.1 Typemaps</H3>
+<p>
+The COM module uses four typemaps for wrapping types. These are
+<tt>comtype</tt> (the type that should be used in the generated
+IDL file ), <tt>ctype</tt> (the corresponding C/C++ type),
+<tt>in</tt> (used when handling a parameter to a function - basically
+it needs to convert from the type specified by <tt>ctype</tt> to
+the C/C++ type expected by the function) and <tt>out</tt> (used
+when handling return values). You can also use standard SWIG typemaps
+such as <tt>freearg</tt> and <tt>argout</tt>.
+</p>
-<H3><a name="com_typemaps"></a>17.5.2 Exception handling</H3>
+<p>
+A good example how the typemaps work is the <tt>char *</tt>
+typemap. Its <tt>comtype</tt> is <tt>BSTR</tt> - the de facto standard
+string type in COM, essentially an array of wide characters with
+a four byte length prefix. The corresponding <tt>ctype</tt> is
+<tt>WCHAR *</tt>. The typemaps for handling <tt>char *</tt> strings could
+look like this:
+</p>
+<div class="code">
+<pre>
+%typemap(ctype) char *, char[], char[ANY] "WCHAR *"
+%typemap(comtype) char *, char[], char[ANY] "BSTR"
+
+%typemap(in) char *, char[], char[ANY] {
+ if ($input) {
+ int SWIG_len = WideCharToMultiByte(CP_ACP, 0, $input, -1, 0, 0, 0, 0);
+ $1 = ($1_ltype) malloc(SWIG_len);
+ WideCharToMultiByte(CP_ACP, 0, $input, -1, (char *) $1, SWIG_len, 0, 0);
+ }
+}
+
+%typemap(freearg) char *, char[], char[ANY] {
+ if ($input) {
+ free($1);
+ }
+}
+
+%typemap(out) char *, char[], char[ANY] %{
+ if ($1) {
+ int SWIG_len = MultiByteToWideChar(CP_ACP, 0, (char *) $1, -1, 0, 0);
+ WCHAR *SWIG_res = (WCHAR *) CoTaskMemAlloc((SWIG_len + 2) * sizeof(WCHAR));
+ /* First 4 bytes contain length in bytes */
+ *((unsigned int *) SWIG_res) = (unsigned int) (SWIG_len - 1) * sizeof(WCHAR);
+ MultiByteToWideChar(CP_ACP, 0, (char *) $1, -1, SWIG_res + 2, SWIG_len);
+ $result = SWIG_res + 2;
+ }
+%}
+</pre>
+</div>
</body>
</html>
diff --git a/Examples/Makefile.in b/Examples/Makefile.in
index be4a4152c..adf9488c0 100644
--- a/Examples/Makefile.in
+++ b/Examples/Makefile.in
@@ -1129,7 +1129,7 @@ com_cpp: $(SRCS) $(CXXSRCS)
$(COMPILETOOL) $(COM_RC) $(COM_RC_OUT_SWITCHES)$(COM_RES_FILE) $(COM_RC_IN_SWITCHES) $(COM_RC_FILE)
$(COMPILETOOL) $(COM_CXX) $(COM_CXX_SHARED_SWITCHES) $(COM_CXX_OUT_SWITCHES)$(TARGET).dll$(COM_EXEC_SUFFIX) $(SRCS) $(CXXSRCS) $(ICXXSRCS) $(COM_RES_FILE) $(COM_DEF_FILE) $(COM_LIBS) $(INCLUDES)
-com_compile: $(COMSRCS)
+com_compile:
$(COMPILETOOL) $(COM_CC) $(COM_CC_SWITCHES) $(COM_CC_OUT_SWITCHES)$(TARGET)$(COM_EXEC_SUFFIX) $(COMSRCS) $(COM_LIBS)
com_clean:
diff --git a/Examples/test-suite/com/aggregate_runme.vbs b/Examples/test-suite/com/aggregate_runme.vbs
index ed0a6d206..6da6cf389 100644
--- a/Examples/test-suite/com/aggregate_runme.vbs
+++ b/Examples/test-suite/com/aggregate_runme.vbs
@@ -33,12 +33,11 @@ End If
Rem Confirm that move() raises an exception when the contract is violated
On Error Resume Next
-result = 99
result = aggregate.move(0)
-Rem Second assignment to result should not have been done
+Rem The last statement should have produced an error
-If result <> 99 Then
+If Err.Number = 0 Then
WScript.Echo "0 test failed"
WScript.Quit 1
End If
diff --git a/Lib/com/com.swg b/Lib/com/com.swg
index 10d1825f3..3edfd9439 100644
--- a/Lib/com/com.swg
+++ b/Lib/com/com.swg
@@ -91,7 +91,7 @@
%typemap(in) void ""
%typemap(in) SWIGTYPE *, SWIGTYPE (CLASS::*) %{
- {
+ if ($input) {
SWIGIUnknown *wrapper;
/* Call to QueryInterface */
@@ -112,7 +112,7 @@
%}
%typemap(in) SWIGTYPE & %{
- {
+ if ($input) {
SWIGIUnknown *wrapper;
/* Call to QueryInterface */
@@ -128,6 +128,8 @@
/* Release */
((long (SWIGSTDCALL *)(SWIGIUnknown *)) (wrapper->vtable[2]))(wrapper);
}
+ } else {
+ return $invalidarg;
}
%}
@@ -246,7 +248,9 @@
%}
%typemap(out) SWIGTYPE *, SWIGTYPE (CLASS::*) %{
- $result = (SWIGIUnknown *) SWIG_wrap$comclassname(*(void **) &$1, $owner);
+ if ($1) {
+ $result = (SWIGIUnknown *) SWIG_wrap$comclassname(*(void **) &$1, $owner);
+ }
%}
%typemap(out) SWIGTYPE & %{
@@ -329,7 +333,7 @@ typedef struct {
GUID *additionalIID; /* IID supported by object (apart from IUnknown and IDispatch) */
} SWIGWrappedObject;
-GUID IID_ISWIGWrappedObject = { 0x73738294, 0x8833, 0x1182, { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78 }};
+GUID IID_ISWIGWrappedObject = { 0x1a3a5cc8, 0x9a61, 0x4681, { 0xae, 0x9c, 0xd0, 0x42, 0x93, 0xf3, 0x57, 0x34 }};
static LONG globalRefCount = 0;
static int SWIGIsEqual(const GUID *a, const GUID *b) {
diff --git a/Source/Modules/com.cxx b/Source/Modules/com.cxx
index 26e75703e..02abaec6f 100644
--- a/Source/Modules/com.cxx
+++ b/Source/Modules/com.cxx
@@ -820,12 +820,18 @@ public:
/* Contract macro modification */
Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
- if (hresult_flag)
+ if (hresult_flag) {
Replaceall(f->code, "$null", "E_ABORT");
- else if (!is_void_return)
+ Replaceall(f->code, "$invalidarg", "E_INVALIDARG");
+ }
+ else if (!is_void_return) {
Replaceall(f->code, "$null", "0");
- else
+ Replaceall(f->code, "$invalidarg", "0");
+ }
+ else {
Replaceall(f->code, "$null", "");
+ Replaceall(f->code, "$invalidarg", "");
+ }
Wrapper_print(f, f_wrappers);
diff --git a/configure.in b/configure.in
index cfad94c69..d963bc7a2 100644
--- a/configure.in
+++ b/configure.in
@@ -1891,7 +1891,7 @@ case $host in
AC_CHECK_PROGS(COM_RC, wrc i586-mingw32msvc-windres)
fi
if test -z "$COM_CSCRIPT" ; then
- AC_CHECK_PROGS(COM_CSCRIPT, cscript echo)
+ AC_CHECK_PROGS(COM_CSCRIPT, cscript true)
fi
;;
esac