1/* ----------------------------------------------------------------------------- 2 * dhead.swg 3 * 4 * Support code for exceptions if the SWIG_D_NO_EXCEPTION_HELPER is not defined 5 * Support code for strings if the SWIG_D_NO_STRING_HELPER is not defined 6 * 7 * Support code for function pointers. ----------------------------------------------------------------------------- */ 8 9%insert(runtime) %{ 10#include <stdlib.h> 11#include <string.h> 12#include <stdio.h> 13 14/* Contract support. */ 15#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_DSetPendingException(SWIG_DException, msg); return nullreturn; } else 16%} 17 18 19/* 20 * Exception support code. 21 */ 22 23#if !defined(SWIG_D_NO_EXCEPTION_HELPER) 24%insert(runtime) %{ 25// Support for throwing D exceptions from C/C++. 26typedef enum { 27 SWIG_DException = 0, 28 SWIG_DIllegalArgumentException, 29 SWIG_DIllegalElementException, 30 SWIG_DIOException, 31 SWIG_DNoSuchElementException, 32} SWIG_DExceptionCodes; 33 34typedef void (* SWIG_DExceptionCallback_t)(const char *); 35 36typedef struct { 37 SWIG_DExceptionCodes code; 38 SWIG_DExceptionCallback_t callback; 39} SWIG_DException_t; 40 41static SWIG_DException_t SWIG_d_exceptions[] = { 42 { SWIG_DException, NULL }, 43 { SWIG_DIllegalArgumentException, NULL }, 44 { SWIG_DIllegalElementException, NULL }, 45 { SWIG_DIOException, NULL }, 46 { SWIG_DNoSuchElementException, NULL } 47}; 48 49static void SWIGUNUSED SWIG_DSetPendingException(SWIG_DExceptionCodes code, const char *msg) { 50 if ((size_t)code < sizeof(SWIG_d_exceptions)/sizeof(SWIG_DException_t)) { 51 SWIG_d_exceptions[code].callback(msg); 52 } else { 53 SWIG_d_exceptions[SWIG_DException].callback(msg); 54 } 55} 56 57#ifdef __cplusplus 58extern "C" 59#endif 60SWIGEXPORT void SWIGRegisterExceptionCallbacks_$module( 61 SWIG_DExceptionCallback_t exceptionCallback, 62 SWIG_DExceptionCallback_t illegalArgumentCallback, 63 SWIG_DExceptionCallback_t illegalElementCallback, 64 SWIG_DExceptionCallback_t ioCallback, 65 SWIG_DExceptionCallback_t noSuchElementCallback) { 66 SWIG_d_exceptions[SWIG_DException].callback = exceptionCallback; 67 SWIG_d_exceptions[SWIG_DIllegalArgumentException].callback = illegalArgumentCallback; 68 SWIG_d_exceptions[SWIG_DIllegalElementException].callback = illegalElementCallback; 69 SWIG_d_exceptions[SWIG_DIOException].callback = ioCallback; 70 SWIG_d_exceptions[SWIG_DNoSuchElementException].callback = noSuchElementCallback; 71} 72%} 73 74#if (SWIG_D_VERSION == 1) 75%pragma(d) imdmoduleimports=%{ 76// Exception throwing support currently requires Tango, but there is no reason 77// why it could not support Phobos. 78static import tango.core.Exception; 79static import tango.core.Thread; 80static import tango.stdc.stringz; 81%} 82 83%pragma(d) imdmodulecode=%{ 84private class SwigExceptionHelper { 85 static this() { 86 swigRegisterExceptionCallbacks$module( 87 &setException, 88 &setIllegalArgumentException, 89 &setIllegalElementException, 90 &setIOException, 91 &setNoSuchElementException); 92 } 93 94 static void setException(char* message) { 95 auto exception = new object.Exception(tango.stdc.stringz.fromStringz(message).dup); 96 exception.next = SwigPendingException.retrieve(); 97 SwigPendingException.set(exception); 98 } 99 100 static void setIllegalArgumentException(char* message) { 101 auto exception = new tango.core.Exception.IllegalArgumentException(tango.stdc.stringz.fromStringz(message).dup); 102 exception.next = SwigPendingException.retrieve(); 103 SwigPendingException.set(exception); 104 } 105 106 static void setIllegalElementException(char* message) { 107 auto exception = new tango.core.Exception.IllegalElementException(tango.stdc.stringz.fromStringz(message).dup); 108 exception.next = SwigPendingException.retrieve(); 109 SwigPendingException.set(exception); 110 } 111 112 static void setIOException(char* message) { 113 auto exception = new tango.core.Exception.IOException(tango.stdc.stringz.fromStringz(message).dup); 114 exception.next = SwigPendingException.retrieve(); 115 SwigPendingException.set(exception); 116 } 117 118 static void setNoSuchElementException(char* message) { 119 auto exception = new tango.core.Exception.NoSuchElementException(tango.stdc.stringz.fromStringz(message).dup); 120 exception.next = SwigPendingException.retrieve(); 121 SwigPendingException.set(exception); 122 } 123} 124 125package class SwigPendingException { 126public: 127 static this() { 128 m_sPendingCount = 0; 129 m_sPendingException = new ThreadLocalData(null); 130 } 131 132 static bool isPending() { 133 bool pending = false; 134 if (m_sPendingCount > 0) { 135 if (m_sPendingException.val !is null) { 136 pending = true; 137 } 138 } 139 return pending; 140 } 141 142 static void set(object.Exception e) { 143 if (m_sPendingException.val !is null) { 144 throw new object.Exception("FATAL: An earlier pending exception from C/C++ code " ~ 145 "was missed and thus not thrown (" ~ m_sPendingException.val.classinfo.name ~ 146 ": " ~ m_sPendingException.val.msg ~ ")!", e); 147 } 148 149 m_sPendingException.val = e; 150 synchronized { 151 ++m_sPendingCount; 152 } 153 } 154 155 static object.Exception retrieve() { 156 object.Exception e = null; 157 if (m_sPendingCount > 0) { 158 if (m_sPendingException.val !is null) { 159 e = m_sPendingException.val; 160 m_sPendingException.val = null; 161 synchronized { 162 --m_sPendingCount; 163 } 164 } 165 } 166 return e; 167 } 168 169private: 170 // The pending exception counter is stored thread-global. 171 static int m_sPendingCount; 172 173 // The reference to the pending exception (if any) is stored thread-local. 174 alias tango.core.Thread.ThreadLocal!(object.Exception) ThreadLocalData; 175 static ThreadLocalData m_sPendingException; 176} 177alias void function(char* message) SwigExceptionCallback; 178%} 179#else 180%pragma(d) imdmoduleimports=%{ 181static import std.conv; 182%} 183 184%pragma(d) imdmodulecode=%{ 185private class SwigExceptionHelper { 186 static this() { 187 // The D1/Tango version maps C++ exceptions to multiple exception types. 188 swigRegisterExceptionCallbacks$module( 189 &setException, 190 &setException, 191 &setException, 192 &setException, 193 &setException 194 ); 195 } 196 197 static void setException(const char* message) { 198 auto exception = new object.Exception(std.conv.to!string(message).idup); 199 exception.next = SwigPendingException.retrieve(); 200 SwigPendingException.set(exception); 201 } 202} 203 204package struct SwigPendingException { 205public: 206 static this() { 207 m_sPendingCount = 0; 208 m_sPendingException = null; 209 } 210 211 static bool isPending() { 212 bool pending = false; 213 if (m_sPendingCount > 0) { 214 if (m_sPendingException !is null) { 215 pending = true; 216 } 217 } 218 return pending; 219 } 220 221 static void set(object.Exception e) { 222 if (m_sPendingException !is null) { 223 throw new object.Exception("FATAL: An earlier pending exception from C/C++ code " ~ 224 "was missed and thus not thrown (" ~ m_sPendingException.classinfo.name ~ 225 ": " ~ m_sPendingException.msg ~ ")!", e); 226 } 227 228 m_sPendingException = e; 229 synchronized { 230 ++m_sPendingCount; 231 } 232 } 233 234 static object.Exception retrieve() { 235 object.Exception e = null; 236 if (m_sPendingCount > 0) { 237 if (m_sPendingException !is null) { 238 e = m_sPendingException; 239 m_sPendingException = null; 240 synchronized { 241 --m_sPendingCount; 242 } 243 } 244 } 245 return e; 246 } 247 248private: 249 // The pending exception counter is stored thread-global. 250 static shared int m_sPendingCount; 251 252 // The reference to the pending exception (if any) is stored thread-local. 253 static object.Exception m_sPendingException; 254} 255alias void function(const char* message) SwigExceptionCallback; 256%} 257#endif 258// Callback registering function in wrapperloader.swg. 259#endif // SWIG_D_NO_EXCEPTION_HELPER 260 261 262/* 263 * String support code. 264 */ 265 266#if !defined(SWIG_D_NO_STRING_HELPER) 267%insert(runtime) %{ 268// Callback for returning strings to D without leaking memory. 269typedef char * (* SWIG_DStringHelperCallback)(const char *); 270static SWIG_DStringHelperCallback SWIG_d_string_callback = NULL; 271 272#ifdef __cplusplus 273extern "C" 274#endif 275SWIGEXPORT void SWIGRegisterStringCallback_$module(SWIG_DStringHelperCallback callback) { 276 SWIG_d_string_callback = callback; 277} 278%} 279 280#if (SWIG_D_VERSION == 1) 281%pragma(d) imdmoduleimports = "static import tango.stdc.stringz;"; 282 283%pragma(d) imdmodulecode = %{ 284private class SwigStringHelper { 285 static this() { 286 swigRegisterStringCallback$module(&createString); 287 } 288 289 static char* createString(char* cString) { 290 // We are effectively dup'ing the string here. 291 return tango.stdc.stringz.toStringz(tango.stdc.stringz.fromStringz(cString)); 292 } 293} 294alias char* function(char* cString) SwigStringCallback; 295%} 296#else 297%pragma(d) imdmoduleimports = %{ 298static import std.conv; 299static import std.string; 300%} 301 302%pragma(d) imdmodulecode = %{ 303private class SwigStringHelper { 304 static this() { 305 swigRegisterStringCallback$module(&createString); 306 } 307 308 static const(char)* createString(const(char*) cString) { 309 // We are effectively dup'ing the string here. 310 // TODO: Is this also correct for D2/Phobos? 311 return std.string.toStringz(std.conv.to!string(cString)); 312 } 313} 314alias const(char)* function(const(char*) cString) SwigStringCallback; 315%} 316#endif 317// Callback registering function in wrapperloader.swg. 318#endif // SWIG_D_NO_STRING_HELPER 319 320 321/* 322 * Function pointer support code. 323 */ 324#if (SWIG_D_VERSION == 1) 325%pragma(d) imdmodulecode = %{ 326template SwigExternC(T) { 327 static if (is(typeof(*(T.init)) R == return)) { 328 static if (is(typeof(*(T.init)) P == function)) { 329 alias extern(C) R function(P) SwigExternC; 330 } 331 } 332} 333%} 334#else 335%pragma(d) imdmodulecode = %{ 336template SwigExternC(T) if (is(typeof(*(T.init)) P == function)) { 337 static if (is(typeof(*(T.init)) R == return)) { 338 static if (is(typeof(*(T.init)) P == function)) { 339 alias extern(C) R function(P) SwigExternC; 340 } 341 } 342} 343%} 344#endif 345