00001 //================================================================================================= 00002 // Copyright (c) 2012, Johannes Meyer, TU Darmstadt 00003 // All rights reserved. 00004 00005 // Redistribution and use in source and binary forms, with or without 00006 // modification, are permitted provided that the following conditions are met: 00007 // * Redistributions of source code must retain the above copyright 00008 // notice, this list of conditions and the following disclaimer. 00009 // * Redistributions in binary form must reproduce the above copyright 00010 // notice, this list of conditions and the following disclaimer in the 00011 // documentation and/or other materials provided with the distribution. 00012 // * Neither the name of the Flight Systems and Automatic Control group, 00013 // TU Darmstadt, nor the names of its contributors may be used to 00014 // endorse or promote products derived from this software without 00015 // specific prior written permission. 00016 00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00020 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 //================================================================================================= 00028 00029 #ifndef ROSMATLAB_OBJECT_H 00030 #define ROSMATLAB_OBJECT_H 00031 00032 #include <rosmatlab/exception.h> 00033 #include <boost/shared_ptr.hpp> 00034 #include "mex.h" 00035 00036 #include <stdint.h> 00037 00038 namespace rosmatlab { 00039 00040 namespace { 00041 struct null_deleter { 00042 void operator()(void const *) const {} 00043 }; 00044 } 00045 00046 template <class Type> 00047 class Object 00048 { 00049 public: 00050 typedef boost::shared_ptr<Type> Ptr; 00051 00052 Object() { construct(); } 00053 Object(Type *instance) { *this = instance; construct(); } 00054 Object(const Ptr &instance) { *this = instance; construct(); } 00055 Object(const Object &other) { *this = other; construct(); } 00056 virtual ~Object() { if (handle_) mxDestroyArray(handle_); } 00057 00058 const Ptr &instance() const { return instance_; } 00059 mxArray *handle() const { return handle_; } 00060 00061 Type* get() { return instance_.get(); } 00062 const Type* get() const { return instance_.get(); } 00063 Type &operator*() { return *instance_; } 00064 const Type &operator*() const { return *instance_; } 00065 00066 Object<Type> &operator=(const Object &other) { 00067 return *this = other.instance_; 00068 } 00069 00070 Object<Type> &operator=(Type *instance) { 00071 return *this = Ptr(instance, null_deleter()); 00072 } 00073 00074 Object<Type> &operator=(const Ptr &instance) { 00075 instance_ = instance; 00076 return *this; 00077 } 00078 00079 static Object<Type> *byHandle(const mxArray *handle) { 00080 const mxArray *ptr = 0; 00081 if (!handle) return 0; 00082 // mexPrintf("Searching for object of type %s (class %s)...\n", typeid(Type).name(), mxGetClassName(handle)); 00083 if (mxIsClass(handle, class_name_)) { 00084 ptr = mxGetProperty(handle, 0, "handle"); 00085 } else if (mxIsStruct(handle)) { 00086 ptr = mxGetField(handle, 0, "handle"); 00087 } else if (mxIsDouble(handle)) { 00088 ptr = handle; 00089 } 00090 if (!ptr || !mxIsDouble(ptr) || !mxGetNumberOfElements(ptr) > 0 || !mxGetPr(ptr)) throw Exception("invalid handle"); 00091 00092 Object<Type> *object = reinterpret_cast<Object<Type> *>(static_cast<uint64_t>(*mxGetPr(ptr))); 00093 return object; 00094 } 00095 00096 private: 00097 boost::shared_ptr<Type> instance_; 00098 mxArray *handle_; 00099 static const char *class_name_; 00100 00101 void construct() { 00102 handle_ = mxCreateDoubleScalar(reinterpret_cast<uint64_t>(this)); 00103 mexMakeArrayPersistent(handle_); 00104 assert(byHandle(handle()) == this); 00105 } 00106 }; 00107 00108 template <class Type> 00109 Type *getObject(const mxArray *handle) { 00110 Object<Type> *object = Object<Type>::byHandle(handle); 00111 if (!object) return 0; 00112 return object->get(); 00113 } 00114 00115 } // namespace rosmatlab 00116 00117 #endif // ROSMATLAB_OBJECT_H