You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
382 lines
8.2 KiB
382 lines
8.2 KiB
/* ----------------------------------------------------------------------------- |
|
* See the LICENSE file for information on copyright, usage and redistribution |
|
* of SWIG, and the README file for authors - http://www.swig.org/release.html. |
|
* |
|
* director.swg |
|
* |
|
* This file contains support for director classes that proxy |
|
* method calls from C++ to Ruby extensions. |
|
* ----------------------------------------------------------------------------- */ |
|
|
|
/* |
|
Use -DSWIG_DIRECTOR_NOUEH if you prefer to avoid the use of the |
|
Undefined Exception Handler provided by swift |
|
*/ |
|
#ifndef SWIG_DIRECTOR_NOUEH |
|
#ifndef SWIG_DIRECTOR_UEH |
|
#define SWIG_DIRECTOR_UEH |
|
#endif |
|
#endif |
|
|
|
#ifdef __cplusplus |
|
|
|
#include <string> |
|
#include <iostream> |
|
#include <map> |
|
|
|
namespace Swig { |
|
/* memory handler */ |
|
struct GCItem |
|
{ |
|
virtual ~GCItem() |
|
{ |
|
} |
|
|
|
virtual ruby_owntype get_own() const |
|
{ |
|
return 0; |
|
} |
|
}; |
|
|
|
struct GCItem_var |
|
{ |
|
GCItem_var(GCItem *item = 0) : _item(item) |
|
{ |
|
} |
|
|
|
GCItem_var& operator=(GCItem *item) |
|
{ |
|
GCItem *tmp = _item; |
|
_item = item; |
|
delete tmp; |
|
return *this; |
|
} |
|
|
|
~GCItem_var() |
|
{ |
|
delete _item; |
|
} |
|
|
|
GCItem * operator->() const |
|
{ |
|
return _item; |
|
} |
|
|
|
private: |
|
GCItem *_item; |
|
}; |
|
|
|
|
|
template <typename Type> |
|
struct GCItem_T : GCItem |
|
{ |
|
GCItem_T(Type *ptr) : _ptr(ptr) |
|
{ |
|
} |
|
|
|
virtual ~GCItem_T() |
|
{ |
|
delete _ptr; |
|
} |
|
|
|
private: |
|
Type *_ptr; |
|
}; |
|
|
|
struct GCItem_Object : GCItem |
|
{ |
|
GCItem_Object(ruby_owntype own) : _own(own) |
|
{ |
|
} |
|
|
|
virtual ~GCItem_Object() |
|
{ |
|
} |
|
|
|
ruby_owntype get_own() const |
|
{ |
|
return _own; |
|
} |
|
|
|
private: |
|
ruby_owntype _own; |
|
}; |
|
|
|
|
|
template <typename Type> |
|
struct GCArray_T : GCItem |
|
{ |
|
GCArray_T(Type *ptr) : _ptr(ptr) |
|
{ |
|
} |
|
|
|
virtual ~GCArray_T() |
|
{ |
|
delete[] _ptr; |
|
} |
|
|
|
private: |
|
Type *_ptr; |
|
}; |
|
|
|
|
|
/* body args */ |
|
struct body_args { |
|
VALUE recv; |
|
ID id; |
|
int argc; |
|
VALUE *argv; |
|
}; |
|
|
|
/* Base class for director exceptions */ |
|
class DirectorException { |
|
protected: |
|
VALUE swig_error; |
|
std::string swig_msg; |
|
protected: |
|
DirectorException(VALUE error) |
|
: swig_error(error) |
|
{ |
|
} |
|
|
|
DirectorException(VALUE error, const char* hdr, const char* msg ="") |
|
: swig_error(error), swig_msg(hdr) { |
|
if (strlen(msg)) { |
|
swig_msg += " "; |
|
swig_msg += msg; |
|
} |
|
if (swig_msg.size()) { |
|
VALUE str = rb_str_new(swig_msg.data(), swig_msg.size()); |
|
swig_error = rb_exc_new3(error, str); |
|
} else { |
|
swig_error = error; |
|
} |
|
} |
|
public: |
|
VALUE getType() const { |
|
return CLASS_OF(swig_error); |
|
} |
|
VALUE getError() const { |
|
return swig_error; |
|
} |
|
const std::string& getMessage() const |
|
{ |
|
return swig_msg; |
|
} |
|
|
|
virtual ~DirectorException() {} |
|
}; |
|
|
|
/* unknown exception handler */ |
|
|
|
class UnknownExceptionHandler |
|
{ |
|
#ifdef SWIG_DIRECTOR_UEH |
|
static void handler() { |
|
try { |
|
throw; |
|
} catch (DirectorException& e) { |
|
std::cerr << "Swig Director exception caught:" << std::endl |
|
<< e.getMessage() << std::endl; |
|
} catch (std::exception& e) { |
|
std::cerr << "std::exception caught: "<< e.what() << std::endl; |
|
} catch (...) { |
|
std::cerr << "Unknown exception caught." << std::endl; |
|
} |
|
std::cerr << std::endl |
|
<< "Ruby interpreter traceback:" << std::endl; |
|
std::cerr << std::endl; |
|
std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl |
|
<< "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl |
|
<< std::endl |
|
<< "Exception is being re-thrown, program will like abort/terminate." << std::endl; |
|
throw; |
|
} |
|
|
|
public: |
|
std::unexpected_handler old; |
|
UnknownExceptionHandler(std::unexpected_handler nh = handler) |
|
{ |
|
old = std::set_unexpected(nh); |
|
} |
|
|
|
~UnknownExceptionHandler() |
|
{ |
|
std::set_unexpected(old); |
|
} |
|
#endif |
|
}; |
|
|
|
|
|
/* Type mismatch in the return value from a Ruby method call */ |
|
class DirectorTypeMismatchException : public Swig::DirectorException { |
|
public: |
|
DirectorTypeMismatchException(VALUE error, const char *msg="") |
|
: Swig::DirectorException(error, "Swig director type mismatch", msg) |
|
{ |
|
} |
|
|
|
DirectorTypeMismatchException(const char *msg="") |
|
: Swig::DirectorException(rb_eTypeError, "Swig director type mismatch", msg) |
|
{ |
|
} |
|
|
|
static void raise(VALUE error, const char *msg) { |
|
throw DirectorTypeMismatchException(error, msg); |
|
} |
|
|
|
static void raise(const char *msg) { |
|
throw DirectorTypeMismatchException(msg); |
|
} |
|
}; |
|
|
|
/* Any Ruby exception that occurs during a director method call */ |
|
class DirectorMethodException : public Swig::DirectorException { |
|
public: |
|
DirectorMethodException(VALUE error) |
|
: Swig::DirectorException(error) { |
|
} |
|
|
|
DirectorMethodException(const char* msg = "") |
|
: Swig::DirectorException(rb_eRuntimeError, "Swig director method error.", msg) { |
|
} |
|
|
|
static void raise(VALUE error) |
|
{ |
|
throw DirectorMethodException(error); |
|
} |
|
}; |
|
|
|
/* Attempted to call a pure virtual method via a director method */ |
|
class DirectorPureVirtualException : public Swig::DirectorException |
|
{ |
|
public: |
|
DirectorPureVirtualException(const char* msg = "") |
|
: DirectorException(rb_eRuntimeError, "Swig director pure virtual method called", msg) |
|
{ |
|
} |
|
|
|
static void raise(const char *msg) |
|
{ |
|
throw DirectorPureVirtualException(msg); |
|
} |
|
}; |
|
|
|
/* Simple thread abstraction for pthreads on win32 */ |
|
#ifdef __THREAD__ |
|
# define __PTHREAD__ |
|
# if defined(_WIN32) || defined(__WIN32__) |
|
# define pthread_mutex_lock EnterCriticalSection |
|
# define pthread_mutex_unlock LeaveCriticalSection |
|
# define pthread_mutex_t CRITICAL_SECTION |
|
# define SWIG_MUTEX_INIT(var) var |
|
# else |
|
# include <pthread.h> |
|
# define SWIG_MUTEX_INIT(var) var = PTHREAD_MUTEX_INITIALIZER |
|
# endif |
|
#endif |
|
|
|
#ifdef __PTHREAD__ |
|
struct Guard |
|
{ |
|
pthread_mutex_t *_mutex; |
|
|
|
Guard(pthread_mutex_t &mutex) : _mutex(&mutex) |
|
{ |
|
pthread_mutex_lock(_mutex); |
|
} |
|
|
|
~Guard() |
|
{ |
|
pthread_mutex_unlock(_mutex); |
|
} |
|
}; |
|
# define SWIG_GUARD(mutex) Guard _guard(mutex) |
|
#else |
|
# define SWIG_GUARD(mutex) |
|
#endif |
|
|
|
/* director base class */ |
|
class Director { |
|
private: |
|
/* pointer to the wrapped Ruby object */ |
|
VALUE swig_self; |
|
/* flag indicating whether the object is owned by Ruby or c++ */ |
|
mutable bool swig_disown_flag; |
|
|
|
public: |
|
/* wrap a Ruby object, optionally taking ownership */ |
|
Director(VALUE self) : swig_self(self), swig_disown_flag(false) { |
|
} |
|
|
|
/* discard our reference at destruction */ |
|
virtual ~Director() { |
|
} |
|
|
|
/* return a pointer to the wrapped Ruby object */ |
|
VALUE swig_get_self() const { |
|
return swig_self; |
|
} |
|
|
|
/* acquire ownership of the wrapped Ruby object (the sense of "disown" |
|
* is from Ruby) */ |
|
void swig_disown() const { |
|
if (!swig_disown_flag) { |
|
swig_disown_flag = true; |
|
} |
|
} |
|
|
|
/* ownership management */ |
|
private: |
|
typedef std::map<void*, GCItem_var> ownership_map; |
|
mutable ownership_map owner; |
|
#ifdef __PTHREAD__ |
|
static pthread_mutex_t swig_mutex_own; |
|
#endif |
|
|
|
public: |
|
template <typename Type> |
|
void swig_acquire_ownership_array(Type *vptr) const |
|
{ |
|
if (vptr) { |
|
SWIG_GUARD(swig_mutex_own); |
|
owner[vptr] = new GCArray_T<Type>(vptr); |
|
} |
|
} |
|
|
|
template <typename Type> |
|
void swig_acquire_ownership(Type *vptr) const |
|
{ |
|
if (vptr) { |
|
SWIG_GUARD(swig_mutex_own); |
|
owner[vptr] = new GCItem_T<Type>(vptr); |
|
} |
|
} |
|
|
|
void swig_acquire_ownership_obj(void *vptr, ruby_owntype own) const |
|
{ |
|
if (vptr && own) { |
|
SWIG_GUARD(swig_mutex_own); |
|
owner[vptr] = new GCItem_Object(own); |
|
} |
|
} |
|
|
|
ruby_owntype swig_release_ownership(void *vptr) const |
|
{ |
|
ruby_owntype own = 0; |
|
if (vptr) { |
|
SWIG_GUARD(swig_mutex_own); |
|
ownership_map::iterator iter = owner.find(vptr); |
|
if (iter != owner.end()) { |
|
own = iter->second->get_own(); |
|
owner.erase(iter); |
|
} |
|
} |
|
return own; |
|
} |
|
}; |
|
} |
|
|
|
#endif /* __cplusplus */ |
|
|
|
|
|
|