multipatch.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. #ifndef _WASABI_MULTIPATCH_H
  2. #define _WASABI_MULTIPATCH_H
  3. // (c) 2005 Nullsoft, Inc.
  4. #include "dispatch.h"
  5. /*
  6. Author: Ben Allison <[email protected]>
  7. The purpose of the MultiPatch class is to allow a class to have multiple Dispatchable interfaces.
  8. It is an alternative to the method of using a stub class with virtual functions.
  9. (you see these classes all over Wasabi, either ending in I or X, depending on age)
  10. Since each vtable entry costs 4 bytes per object (8 on 64bit), using this method adds some code size
  11. (and, in some multiple-inheritance situations, memory per object for vtable overrides)
  12. Of course, MultiPatch's dispatching function adds code size, too. But the function shouldn't be any
  13. larger or slower than the dispatching in the api_X class anyway.
  14. Using MultiPatch, each method call goes through this chain:
  15. dispatch->multipatch->your class method
  16. as opposed to:
  17. dispatch->your class method (single inheritance)
  18. or:
  19. dispatch->virtual function->your class method (api_X method)
  20. A clever compiler might be able to optimize away the _multipatch function call by
  21. pushing "patch" on the top of the parameter stack and jmp'ing.
  22. For an example on usage, scroll down to the bottom of the page.
  23. */
  24. template <int patch_t, class base_t>
  25. class MultiPatch : public base_t
  26. {
  27. protected:
  28. virtual int _multipatch(int patch, int msg, void *retval, void **params=0, int nparam=0) = 0;
  29. private:
  30. int _dispatch(int msg, void *retval, void **params=0, int nparam=0)
  31. {
  32. return _multipatch(patch_t, msg, retval, params, nparam);
  33. }
  34. public:
  35. /* these helper functions are a direct copy from Dispatchable...
  36. * They need to be duplicated, because the compiler gets confused when trying to cast
  37. * from Dispatchable to the child class (since that class has multiple Dispatchable parents)
  38. *
  39. * They could potentially be eliminated by modifying Dispatchable's versions, but the risk of breakage
  40. * isn't worth it.
  41. */
  42. template <class CLASSNAME, class RETVAL>
  43. void cb(RETVAL (CLASSNAME::*fn)(), void *retval, void **params) {
  44. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)();
  45. }
  46. template <class CLASSNAME>
  47. void vcb(void (CLASSNAME::*fn)(), void *retval, void **params) {
  48. (static_cast<CLASSNAME *>(this)->*fn)();
  49. }
  50. template <class CLASSNAME, class RETVAL, class PARAM1>
  51. void cb(RETVAL (CLASSNAME::*fn)(PARAM1), void *retval, void **params) {
  52. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  53. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1);
  54. }
  55. template <class CLASSNAME, class PARAM1>
  56. void vcb(void (CLASSNAME::*fn)(PARAM1), void *retval, void **params) {
  57. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  58. (static_cast<CLASSNAME *>(this)->*fn)(*p1);
  59. }
  60. template <class CLASSNAME, class PARAM1, class PARAM2>
  61. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2), void *retval, void **params) {
  62. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  63. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  64. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2);
  65. }
  66. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2>
  67. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2), void *retval, void **params) {
  68. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  69. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  70. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2);
  71. }
  72. // 3 params
  73. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3>
  74. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3), void *retval, void **params) {
  75. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  76. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  77. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  78. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3);
  79. }
  80. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3>
  81. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3), void *retval, void **params) {
  82. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  83. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  84. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  85. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3);
  86. }
  87. // 4 params
  88. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4>
  89. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4), void *retval, void **params) {
  90. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  91. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  92. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  93. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  94. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4);
  95. }
  96. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4>
  97. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4), void *retval, void **params) {
  98. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  99. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  100. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  101. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  102. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4);
  103. }
  104. // 5 params
  105. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
  106. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5), void *retval, void **params) {
  107. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  108. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  109. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  110. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  111. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  112. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5);
  113. }
  114. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5>
  115. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5), void *retval, void **params) {
  116. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  117. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  118. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  119. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  120. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  121. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5);
  122. }
  123. // 6 params
  124. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
  125. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6), void *retval, void **params) {
  126. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  127. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  128. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  129. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  130. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  131. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  132. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6);
  133. }
  134. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6>
  135. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6), void *retval, void **params) {
  136. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  137. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  138. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  139. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  140. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  141. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  142. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6);
  143. }
  144. // 7 params
  145. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
  146. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7), void *retval, void **params) {
  147. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  148. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  149. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  150. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  151. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  152. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  153. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  154. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7);
  155. }
  156. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7>
  157. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7), void *retval, void **params) {
  158. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  159. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  160. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  161. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  162. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  163. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  164. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  165. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7);
  166. }
  167. // 8 params
  168. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
  169. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8), void *retval, void **params) {
  170. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  171. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  172. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  173. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  174. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  175. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  176. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  177. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  178. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8);
  179. }
  180. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8>
  181. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8), void *retval, void **params) {
  182. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  183. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  184. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  185. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  186. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  187. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  188. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  189. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  190. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8);
  191. }
  192. // 9 params
  193. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
  194. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9), void *retval, void **params) {
  195. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  196. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  197. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  198. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  199. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  200. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  201. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  202. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  203. PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
  204. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9);
  205. }
  206. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9>
  207. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9), void *retval, void **params) {
  208. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  209. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  210. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  211. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  212. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  213. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  214. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  215. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  216. PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
  217. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9);
  218. }
  219. // 10 params
  220. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
  221. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10), void *retval, void **params) {
  222. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  223. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  224. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  225. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  226. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  227. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  228. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  229. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  230. PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
  231. PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
  232. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10);
  233. }
  234. template <class CLASSNAME, class RETVAL, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10>
  235. void cb(RETVAL (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10), void *retval, void **params) {
  236. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  237. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  238. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  239. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  240. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  241. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  242. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  243. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  244. PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
  245. PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
  246. *static_cast<RETVAL*>(retval) = (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10);
  247. }
  248. // 14 params
  249. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14>
  250. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14), void *retval, void **params) {
  251. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  252. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  253. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  254. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  255. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  256. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  257. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  258. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  259. PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
  260. PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
  261. PARAM11 *p11 = static_cast<PARAM11*>(params[10]);
  262. PARAM12 *p12 = static_cast<PARAM12*>(params[11]);
  263. PARAM13 *p13 = static_cast<PARAM13*>(params[12]);
  264. PARAM14 *p14 = static_cast<PARAM14*>(params[13]);
  265. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14);
  266. }
  267. // 16 params
  268. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16>
  269. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14, PARAM15, PARAM16), void *retval, void **params) {
  270. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  271. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  272. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  273. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  274. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  275. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  276. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  277. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  278. PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
  279. PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
  280. PARAM11 *p11 = static_cast<PARAM11*>(params[10]);
  281. PARAM12 *p12 = static_cast<PARAM12*>(params[11]);
  282. PARAM13 *p13 = static_cast<PARAM13*>(params[12]);
  283. PARAM14 *p14 = static_cast<PARAM14*>(params[13]);
  284. PARAM15 *p15 = static_cast<PARAM15*>(params[14]);
  285. PARAM16 *p16 = static_cast<PARAM16*>(params[15]);
  286. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14, *p15, *p16);
  287. }
  288. // 17 params
  289. template <class CLASSNAME, class PARAM1, class PARAM2, class PARAM3, class PARAM4, class PARAM5, class PARAM6, class PARAM7, class PARAM8, class PARAM9, class PARAM10, class PARAM11, class PARAM12, class PARAM13, class PARAM14, class PARAM15, class PARAM16, class PARAM17>
  290. void vcb(void (CLASSNAME::*fn)(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7, PARAM8, PARAM9, PARAM10, PARAM11, PARAM12, PARAM13, PARAM14, PARAM15, PARAM16, PARAM17), void *retval, void **params) {
  291. PARAM1 *p1 = static_cast<PARAM1*>(params[0]);
  292. PARAM2 *p2 = static_cast<PARAM2*>(params[1]);
  293. PARAM3 *p3 = static_cast<PARAM3*>(params[2]);
  294. PARAM4 *p4 = static_cast<PARAM4*>(params[3]);
  295. PARAM5 *p5 = static_cast<PARAM5*>(params[4]);
  296. PARAM6 *p6 = static_cast<PARAM6*>(params[5]);
  297. PARAM7 *p7 = static_cast<PARAM7*>(params[6]);
  298. PARAM8 *p8 = static_cast<PARAM8*>(params[7]);
  299. PARAM9 *p9 = static_cast<PARAM9*>(params[8]);
  300. PARAM10 *p10 = static_cast<PARAM10*>(params[9]);
  301. PARAM11 *p11 = static_cast<PARAM11*>(params[10]);
  302. PARAM12 *p12 = static_cast<PARAM12*>(params[11]);
  303. PARAM13 *p13 = static_cast<PARAM13*>(params[12]);
  304. PARAM14 *p14 = static_cast<PARAM14*>(params[13]);
  305. PARAM15 *p15 = static_cast<PARAM15*>(params[14]);
  306. PARAM16 *p16 = static_cast<PARAM16*>(params[15]);
  307. PARAM17 *p17 = static_cast<PARAM17*>(params[16]);
  308. (static_cast<CLASSNAME *>(this)->*fn)(*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12, *p13, *p14, *p15, *p16, *p17);
  309. }
  310. };
  311. #define RECVS_MULTIPATCH int _multipatch(int patch, int msg, void *retval, void **params=0, int nparam=0)
  312. #define START_MULTIPATCH \
  313. int CBCLASS::_multipatch(int patch, int msg, void *retval, void **params, int nparam) { \
  314. switch (patch) {
  315. //FINISH case DESTRUCT: delete this; return 1;
  316. #define END_MULTIPATCH \
  317. default: return 0; \
  318. } \
  319. return 1; \
  320. }
  321. #define FORWARD_MULTIPATCH(x) \
  322. default: return x::_multipatch(patch, msg, retval, params, nparam); \
  323. } \
  324. return 1; \
  325. }
  326. #define START_PATCH(x) case x: switch(msg) {
  327. #define END_PATCH default: return 0; } break;
  328. #define NEXT_PATCH(x) END_PATCH START_PATCH(x)
  329. #define M_CB(p, c, x, y) case (x): MultiPatch<p,c>::cb(&CBCLASS::y, retval, params); break;
  330. #define M_VCB(p, c, x, y) case (x): MultiPatch<p,c>::vcb(&CBCLASS::y, retval, params); break;
  331. #define MULTIPATCH_CODES enum
  332. #endif
  333. /* use example:
  334. enum
  335. {
  336. Test_Patch1 = 10,
  337. Test_Patch2 = 20,
  338. };
  339. class Test : public MultiPatch<Test_Patch1, api_class1>,
  340. public MultiPatch<Test_Patch2, api_class2>
  341. {
  342. public:
  343. int TestFunc1();
  344. void TestFunc2();
  345. void TestFunc3();
  346. protected:
  347. RECVS_MULTIPATCH;
  348. };
  349. #ifdef CBCLASS
  350. #undef CBCLASS
  351. #endif
  352. #define CBCLASS Test
  353. START_MULTIPATCH;
  354. START_PATCH(Test_Patch1)
  355. M_CB(Test_Patch1, api_class1, API_CLASS1_FUNC1, TestFunc1);
  356. NEXT_PATCH(Test_Patch2)
  357. M_VCB(Test_Patch2, api_class2, API_CLASS1_FUNC1, TestFunc2);
  358. M_VCB(Test_Patch2, api_class2, API_CLASS1_FUNC2, TestFunc3);
  359. END_PATCH
  360. END_MULTIPATCH;
  361. #undef CBCLASS
  362. */