00001 #ifndef OBJECT_METHODS_H
00002 #define OBJECT_METHODS_H
00003
00004 #include "calling_convention.h"
00005 #include "global_function.h"
00006 #include <boost/utility/enable_if.hpp>
00007
00008 void AS_StdcallFunctionsCannotBeObjectMethods(Undefined &);
00009
00010 template <typename T, typename Fn, typename D = void>
00011 struct ObjectMethod {
00012 ObjectMethod() {
00013 CallingConvention<Fn>();
00014 }
00015
00016 static std::string signature(const std::string & name);
00017 static asSFuncPtr convert(Fn);
00018 static const asDWORD calling_convention;
00019 };
00020
00021 template <typename T, typename Fn>
00022 struct ObjectMethod<T, Fn,
00023 typename boost::enable_if<
00024 boost::integral_constant<bool,
00025 (CallingConvention<Fn>::value == asCALL_THISCALL)
00026 >
00027 >::type>
00028 : boost::integral_constant<bool,
00029 boost::is_base_of<typename CallingConvention<Fn>::ObjectType, T>::value &&
00030 CallingConvention<Fn>::valid_object_method> {
00031 static std::string signature(const std::string & name) {
00032 return CallingConvention<Fn>::object_method_signature(name);
00033 }
00034
00035 static const asDWORD calling_convention = asCALL_THISCALL;
00036
00037 static asSFuncPtr convert(Fn fn) {
00038 return asSMethodPtr<sizeof(void (T::*)())>::Convert((void (T::*)())(fn));
00039 }
00040 };
00041
00042 template <typename ClassType, typename T>
00043 struct IsValidClassArgType : boost::false_type {};
00044
00045 template <typename ClassType, typename T>
00046 struct IsValidClassArgType<ClassType, T *> : boost::is_base_of<T, ClassType> {};
00047 template <typename ClassType, typename T>
00048 struct IsValidClassArgType<ClassType, const T *> : boost::is_base_of<T, ClassType> {};
00049 template <typename ClassType, typename T>
00050 struct IsValidClassArgType<ClassType, T &> : boost::is_base_of<T, ClassType> {};
00051 template <typename ClassType, typename T>
00052 struct IsValidClassArgType<ClassType, const T &> : boost::is_base_of<T, ClassType> {};
00053
00054 template <typename ClassType, typename T>
00055 struct IsValidClassArgType<ClassType, ObjectProxy<T> *> : boost::is_base_of<T, ClassType> {};
00056 template <typename ClassType, typename T>
00057 struct IsValidClassArgType<ClassType, const ObjectProxy<T> *> : boost::is_base_of<T, ClassType> {};
00058 template <typename ClassType, typename T>
00059 struct IsValidClassArgType<ClassType, ObjectProxy<T> &> : boost::is_base_of<T, ClassType> {};
00060 template <typename ClassType, typename T>
00061 struct IsValidClassArgType<ClassType, const ObjectProxy<T> &> : boost::is_base_of<T, ClassType> {};
00062
00063 template <typename T, typename Fn>
00064 struct ObjectMethod<T, Fn,
00065 typename boost::enable_if<
00066 boost::integral_constant<bool,
00067 (CallingConvention<Fn>::value == asCALL_CDECL)
00068 >
00069 >::type>
00070 : boost::integral_constant<bool,
00071 (IsValidClassArgType<T, typename CallingConvention<Fn>::FirstType>::value &&
00072 CallingConvention<Fn>::is_valid_firstcall_method) ||
00073 (IsValidClassArgType<T, typename CallingConvention<Fn>::LastType>::value &&
00074 CallingConvention<Fn>::is_valid_lastcall_method)>
00075 {
00076 static std::string signature(const std::string & name) {
00077 return do_signature(name, boost::integral_constant<asDWORD, calling_convention>());
00078 }
00079
00080 static std::string do_signature(const std::string & name,
00081 boost::integral_constant<asDWORD, asCALL_CDECL_OBJFIRST>) {
00082 return CallingConvention<Fn>::firstcall_signature(name);
00083 }
00084 static std::string do_signature(const std::string & name,
00085 boost::integral_constant<asDWORD, asCALL_CDECL_OBJLAST>) {
00086 return CallingConvention<Fn>::lastcall_signature(name);
00087 }
00088
00089 static const asDWORD calling_convention
00090 = (IsValidClassArgType<T, typename CallingConvention<Fn>::FirstType>::value &&
00091 CallingConvention<Fn>::is_valid_firstcall_method) ? asCALL_CDECL_OBJFIRST
00092 : asCALL_CDECL_OBJLAST;
00093
00094 static asSFuncPtr convert(Fn fn) {
00095 return asFUNCTION(fn);
00096 }
00097 };
00098
00099 template <typename T, typename Fn>
00100 struct ObjectMethod<T, Fn,
00101 typename boost::enable_if<
00102 boost::integral_constant<bool,
00103 (CallingConvention<Fn>::value == asCALL_STDCALL)
00104 >
00105 >::type> {
00106 ObjectMethod() {
00107 AS_StdcallFunctionsCannotBeObjectMethods(Fn());
00108 }
00109
00110 static std::string signature(const std::string & name);
00111 static asSFuncPtr convert(Fn);
00112 static const asDWORD calling_convention;
00113 };
00114
00115
00116 template <typename T, typename Fn>
00117 std::string do_object_method_signature(Fn, const std::string & name, ObjectMethod<T, Fn> om) {
00118 AS_FunctionHasInvalidParameters(om);
00119 return ObjectMethod<T, Fn>::signature(name);
00120 }
00121
00122 template <typename T, typename Fn>
00123 std::string object_method_signature(Fn fn, const std::string & name) {
00124 return do_object_method_signature<T>(fn, name, ObjectMethod<T, Fn>());
00125 }
00126
00127 template <typename T, typename Fn>
00128 asSFuncPtr convert_object_method(Fn fn) {
00129 return ObjectMethod<T, Fn>::convert(fn);
00130 }
00131
00132 template <typename T, typename Fn>
00133 asDWORD object_method_calling_conv(Fn) {
00134 return ObjectMethod<T, Fn>::calling_convention;
00135 }
00136
00137
00138 #define REGISTER_OBJECT_METHOD(type, name, fn) \
00139 RegisterObjectMethod( ASTraits<type>::get_name().c_str(), \
00140 object_method_signature<type>(fn, name).c_str(), \
00141 convert_object_method<type>(fn), \
00142 object_method_calling_conv<type>(fn) )
00143
00144 #define REGISTER_OBJECT_BEHAVIOUR(type, behaviour, fn) \
00145 RegisterObjectBehaviour( ASTraits<type>::get_name().c_str(), \
00146 behaviour, \
00147 object_method_signature<type>(fn, "f").c_str(), \
00148 convert_object_method<type>(fn), \
00149 object_method_calling_conv<type>(fn) )
00150
00151 #endif