Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NativeWrapperDefns.h
Go to the documentation of this file.
1 /* Copyright (C) 2009 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17  #include "ps/GameSetup/Config.h"
18 
19 // (NativeWrapperDecls.h set up a lot of the macros we use here)
20 
21 // ScriptInterface_NativeWrapper<T>::call(cx, rval, fptr, args...) will call fptr(cbdata, args...),
22 // and if T != void then it will store the result in rval:
23 
24 // Templated on the return type so void can be handled separately
25 template <typename R>
27  #define OVERLOADS(z, i, data) \
28  template<TYPENAME_T0_HEAD(z,i) typename F> \
29  static void call(JSContext* cx, jsval& rval, F fptr T0_A0(z,i)) { \
30  rval = ScriptInterface::ToJSVal<R>(cx, fptr(ScriptInterface::GetCallbackData(cx) A0_TAIL(z,i))); \
31  }
32 
33  BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
34  #undef OVERLOADS
35 };
36 
37 // Overloaded to ignore the return value from void functions
38 template <>
40  #define OVERLOADS(z, i, data) \
41  template<TYPENAME_T0_HEAD(z,i) typename F> \
42  static void call(JSContext* cx, jsval& /*rval*/, F fptr T0_A0(z,i)) { \
43  fptr(ScriptInterface::GetCallbackData(cx) A0_TAIL(z,i)); \
44  }
45  BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
46  #undef OVERLOADS
47 };
48 
49 // Same idea but for method calls:
50 
51 template <typename R, typename TC>
53  #define OVERLOADS(z, i, data) \
54  template<TYPENAME_T0_HEAD(z,i) typename F> \
55  static void call(JSContext* cx, jsval& rval, TC* c, F fptr T0_A0(z,i)) { \
56  rval = ScriptInterface::ToJSVal<R>(cx, (c->*fptr)( A0(z,i) )); \
57  }
58 
59  BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
60  #undef OVERLOADS
61 };
62 
63 template <typename TC>
65  #define OVERLOADS(z, i, data) \
66  template<TYPENAME_T0_HEAD(z,i) typename F> \
67  static void call(JSContext* /*cx*/, jsval& /*rval*/, TC* c, F fptr T0_A0(z,i)) { \
68  (c->*fptr)( A0(z,i) ); \
69  }
70  BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
71  #undef OVERLOADS
72 };
73 
74 // Fast natives don't trigger the hook we use for profiling, so explicitly
75 // notify the profiler when these functions are being called.
76 // ScriptInterface_impl::Register stores the name in a reserved slot.
77 // (TODO: this doesn't work for functions registered via InterfaceScripted.h.
78 // Maybe we should do some interned JS_GetFunctionId thing.)
79 #define SCRIPT_PROFILE \
80  if (g_ScriptProfilingEnabled) \
81  { \
82  ENSURE(JSVAL_IS_OBJECT(JS_CALLEE(cx, vp)) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)))); \
83  const char* name = "(unknown)"; \
84  jsval nameval; \
85  if (JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &nameval) \
86  && !JSVAL_IS_VOID(nameval)) \
87  name = static_cast<const char*>(JSVAL_TO_PRIVATE(nameval)); \
88  CProfileSampleScript profile(name); \
89  }
90 
91 // JSFastNative-compatible function that wraps the function identified in the template argument list
92 #define OVERLOADS(z, i, data) \
93  template <typename R, TYPENAME_T0_HEAD(z,i) R (*fptr) ( void* T0_TAIL(z,i) )> \
94  JSBool ScriptInterface::call(JSContext* cx, uintN argc, jsval* vp) { \
95  UNUSED2(argc); \
96  SCRIPT_PROFILE \
97  BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
98  jsval rval = JSVAL_VOID; \
99  ScriptInterface_NativeWrapper<R>::call(cx, rval, fptr A0_TAIL(z,i)); \
100  JS_SET_RVAL(cx, vp, rval); \
101  return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \
102  }
103 BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
104 #undef OVERLOADS
105 
106 // Same idea but for methods
107 #define OVERLOADS(z, i, data) \
108  template <typename R, TYPENAME_T0_HEAD(z,i) JSClass* CLS, typename TC, R (TC::*fptr) ( T0(z,i) )> \
109  JSBool ScriptInterface::callMethod(JSContext* cx, uintN argc, jsval* vp) { \
110  UNUSED2(argc); \
111  SCRIPT_PROFILE \
112  if (ScriptInterface::GetClass(cx, JS_THIS_OBJECT(cx, vp)) != CLS) return JS_FALSE; \
113  TC* c = static_cast<TC*>(ScriptInterface::GetPrivate(cx, JS_THIS_OBJECT(cx, vp))); \
114  if (! c) return JS_FALSE; \
115  BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
116  jsval rval = JSVAL_VOID; \
117  ScriptInterface_NativeMethodWrapper<R, TC>::call(cx, rval, c, fptr A0_TAIL(z,i)); \
118  JS_SET_RVAL(cx, vp, rval); \
119  return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \
120  }
121 BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
122 #undef OVERLOADS
123 
124 // Clean up our mess
125 #undef SCRIPT_PROFILE
126 #undef NUMBERED_LIST_HEAD
127 #undef NUMBERED_LIST_TAIL
128 #undef NUMBERED_LIST_BALANCED
129 #undef TYPED_ARGS
130 #undef CONVERT_ARG
131 #undef TYPENAME_T0_HEAD
132 #undef TYPENAME_T0_TAIL
133 #undef T0
134 #undef T0_HEAD
135 #undef T0_TAIL
136 #undef T0_A0
137 #undef A0
138 #undef A0_TAIL
#define SCRIPT_INTERFACE_MAX_ARGS
#define OVERLOADS(z, i, data)