RPC3_Boost.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #ifndef __RPC3_BOOST_H
  11. #define __RPC3_BOOST_H
  12. // Fixes
  13. // error C2504: 'boost::fusion::detail::invoke_impl<Function,Sequence,N,CBI,RandomAccess>' : base class undefined
  14. // This defines the maximum number of parameters you can have
  15. #ifndef BOOST_FUSION_INVOKE_MAX_ARITY
  16. #define BOOST_FUSION_INVOKE_MAX_ARITY 10
  17. #endif
  18. // Boost dependencies
  19. // Boost is assumed to be at C:\boost_1_43_0 based on the project settings
  20. // If this is not where you downloaded boost, change the project settings Configuration Properties / C/C++ / General / Additional Include Directories
  21. // If you don't have boost, get it from http://www.boost.org/users/download/
  22. // If you don't want to use boost, use RPC4 instead which relies on assembly but has fewer features
  23. #include "boost/type_traits.hpp"
  24. #include "boost/function.hpp"
  25. #include "boost/bind.hpp"
  26. #include "boost/mpl/if.hpp"
  27. #include "boost/mpl/apply.hpp"
  28. #include "boost/function_types/parameter_types.hpp"
  29. #include "boost/fusion/container/list/cons.hpp" // boost::fusion::nil
  30. #include "boost/fusion/include/push_back.hpp"
  31. #include "boost/fusion/include/invoke.hpp"
  32. #include "boost/fusion/tuple/tuple.hpp"
  33. #include "boost/fusion/tuple/make_tuple.hpp"
  34. #include "boost/fusion/functional/invocation/invoke.hpp"
  35. #include "boost/type_traits/is_array.hpp"
  36. // Not needed?
  37. //#include <boost/fusion/container/generation/make_vector.hpp>
  38. #include "NetworkIDManager.h"
  39. #include "NetworkIDObject.h"
  40. #include "BitStream.h"
  41. namespace RakNet
  42. {
  43. class RPC3;
  44. class BitStream;
  45. namespace _RPC3
  46. {
  47. enum InvokeResultCodes
  48. {
  49. IRC_SUCCESS,
  50. IRC_NEED_BITSTREAM,
  51. IRC_NEED_NETWORK_ID_MANAGER,
  52. IRC_NEED_NETWORK_ID,
  53. IRC_NEED_CLASS_OBJECT,
  54. };
  55. struct InvokeArgs
  56. {
  57. // Bitstream to use to deserialize
  58. RakNet::BitStream *bitStream;
  59. // NetworkIDManager to use to lookup objects
  60. NetworkIDManager *networkIDManager;
  61. // C++ class member object
  62. NetworkID classMemberObjectId;
  63. // The calling plugin
  64. RPC3 *caller;
  65. // The this pointer for C++
  66. NetworkIDObject *thisPtr;
  67. };
  68. typedef boost::fusion::tuple<bool, boost::function<InvokeResultCodes (InvokeArgs)> > FunctionPointer;
  69. struct StrWithDestructor
  70. {
  71. char *c;
  72. ~StrWithDestructor() {if (c) delete c;}
  73. };
  74. enum RPC3TagFlag
  75. {
  76. RPC3_TAG_FLAG_DEREF=1,
  77. RPC3_TAG_FLAG_ARRAY=2,
  78. };
  79. struct RPC3Tag
  80. {
  81. RPC3Tag() {}
  82. RPC3Tag(void *_v, unsigned int _count, RPC3TagFlag _flag) : v(_v), count(_count), flag((unsigned char)_flag) {}
  83. void* v;
  84. unsigned int count;
  85. unsigned char flag;
  86. };
  87. // Track the pointers tagged with RakNet::_RPC3::Deref
  88. static RPC3Tag __RPC3TagPtrs[BOOST_FUSION_INVOKE_MAX_ARITY+1];
  89. static int __RPC3TagHead=0;
  90. static int __RPC3TagTail=0;
  91. // If this assert hits, then RakNet::_RPC3::Deref was called more times than the argument was passed to the function
  92. static void __RPC3_Tag_AddHead(const RPC3Tag &p)
  93. {
  94. // Update tag if already in array
  95. int i;
  96. for (i=__RPC3TagTail; i!=__RPC3TagHead; i=(i+1)%BOOST_FUSION_INVOKE_MAX_ARITY)
  97. {
  98. if (__RPC3TagPtrs[i].v==p.v)
  99. {
  100. if (p.flag==RPC3_TAG_FLAG_ARRAY)
  101. {
  102. __RPC3TagPtrs[i].count=p.count;
  103. }
  104. __RPC3TagPtrs[i].flag|=p.flag;
  105. return;
  106. }
  107. }
  108. __RPC3TagPtrs[__RPC3TagHead]=p;
  109. __RPC3TagHead = (__RPC3TagHead + 1) % BOOST_FUSION_INVOKE_MAX_ARITY;
  110. assert(__RPC3TagHead!=__RPC3TagTail);
  111. }
  112. static void __RPC3ClearTail(void) {
  113. while (__RPC3TagTail!=__RPC3TagHead)
  114. {
  115. if (__RPC3TagPtrs[__RPC3TagTail].v==0)
  116. __RPC3TagTail = (__RPC3TagTail+1) % BOOST_FUSION_INVOKE_MAX_ARITY;
  117. else
  118. return;
  119. }
  120. }
  121. static bool __RPC3ClearPtr(void* p, RPC3Tag *tag) {
  122. int i;
  123. for (i=__RPC3TagTail; i!=__RPC3TagHead; i=(i+1)%BOOST_FUSION_INVOKE_MAX_ARITY)
  124. {
  125. if (__RPC3TagPtrs[i].v==p)
  126. {
  127. *tag=__RPC3TagPtrs[i];
  128. __RPC3TagPtrs[i].v=0;
  129. __RPC3ClearTail();
  130. return true;
  131. }
  132. }
  133. tag->flag=0;
  134. tag->count=1;
  135. return false;
  136. }
  137. template <class templateType>
  138. inline const templateType& Deref(const templateType & t) {
  139. __RPC3_Tag_AddHead(RPC3Tag((void*)t,1,RPC3_TAG_FLAG_DEREF));
  140. return t;
  141. }
  142. template <class templateType>
  143. inline const templateType& PtrToArray(unsigned int count, const templateType & t) {
  144. __RPC3_Tag_AddHead(RPC3Tag((void*)t,count,RPC3_TAG_FLAG_ARRAY));
  145. return t;
  146. }
  147. struct ReadBitstream
  148. {
  149. static void applyArray(RakNet::BitStream &bitStream, RakNet::BitStream* t){apply(bitStream,t);}
  150. static void apply(RakNet::BitStream &bitStream, RakNet::BitStream* t)
  151. {
  152. BitSize_t numBitsUsed;
  153. bitStream.ReadCompressed(numBitsUsed);
  154. bitStream.Read(t,numBitsUsed);
  155. }
  156. };
  157. //template <typename T>
  158. struct ReadPtr
  159. {
  160. template <typename T2>
  161. static inline void applyArray(RakNet::BitStream &bitStream, T2 *t) {bitStream >> (*t);}
  162. template <typename T2>
  163. static inline void apply(RakNet::BitStream &bitStream, T2 *t) {bitStream >> (*t);}
  164. static inline void apply(RakNet::BitStream &bitStream, char *&t) {applyStr(bitStream, (char *&) t);}
  165. static inline void apply(RakNet::BitStream &bitStream, unsigned char *&t) {applyStr(bitStream, (char *&) t);}
  166. static inline void apply(RakNet::BitStream &bitStream, const char *&t) {applyStr(bitStream, (char *&) t);}
  167. static inline void apply(RakNet::BitStream &bitStream, const unsigned char *&t) {applyStr(bitStream, (char *&) t);}
  168. static inline void applyStr(RakNet::BitStream &bitStream, char *&t)
  169. {
  170. RakNet::RakString rs;
  171. bitStream >> rs;
  172. size_t len = rs.GetLength()+1;
  173. // The caller should have already allocated memory, so we need to free
  174. // it and allocate a new buffer.
  175. RakAssert("Expected allocated array, got NULL" && (NULL != t));
  176. delete [] t;
  177. t = new char [len];
  178. memcpy(t,rs.C_String(),len);
  179. }
  180. };
  181. template< typename T >
  182. struct DoRead
  183. {
  184. typedef typename boost::mpl::if_<
  185. boost::is_convertible<T*,RakNet::BitStream*>,
  186. ReadBitstream,
  187. ReadPtr >::type type;
  188. };
  189. template< typename T >
  190. struct ReadWithoutNetworkIDNoPtr
  191. {
  192. static InvokeResultCodes apply(InvokeArgs &args, T &t)
  193. {
  194. // printf("ReadWithoutNetworkIDNoPtr\n");
  195. DoRead< typename boost::remove_pointer<T>::type >::type::apply(* (args.bitStream),&t);
  196. return IRC_SUCCESS;
  197. }
  198. // typedef boost::mpl::false_ Cleanup;
  199. template< typename T2 >
  200. static void Cleanup(T2 &t) {}
  201. };
  202. template< typename T >
  203. struct ReadWithNetworkIDPtr
  204. {
  205. static InvokeResultCodes apply(InvokeArgs &args, T &t)
  206. {
  207. // printf("ReadWithNetworkIDPtr\n");
  208. // Read the network ID
  209. bool isNull;
  210. args.bitStream->Read(isNull);
  211. if (isNull)
  212. {
  213. t=0;
  214. return IRC_SUCCESS;
  215. }
  216. bool deref, isArray;
  217. args.bitStream->Read(deref);
  218. args.bitStream->Read(isArray);
  219. unsigned int count;
  220. if (isArray)
  221. args.bitStream->ReadCompressed(count);
  222. else
  223. count=1;
  224. NetworkID networkId;
  225. for (unsigned int i=0; i < count; i++)
  226. {
  227. args.bitStream->Read(networkId);
  228. t = args.networkIDManager->GET_OBJECT_FROM_ID< T >(networkId);
  229. if (deref)
  230. {
  231. BitSize_t bitsUsed;
  232. args.bitStream->AlignReadToByteBoundary();
  233. args.bitStream->Read(bitsUsed);
  234. if (t)
  235. {
  236. DoRead< typename boost::remove_pointer<T>::type >::type::apply(* (args.bitStream),t);
  237. }
  238. else
  239. {
  240. // Skip data!
  241. args.bitStream->IgnoreBits(bitsUsed);
  242. }
  243. }
  244. }
  245. return IRC_SUCCESS;
  246. }
  247. template< typename T2 >
  248. static void Cleanup(T2 &t) {}
  249. };
  250. template< typename T >
  251. struct ReadWithoutNetworkIDPtr
  252. {
  253. template <typename T2>
  254. static InvokeResultCodes apply(InvokeArgs &args, T2 &t)
  255. {
  256. // printf("ReadWithoutNetworkIDPtr\n");
  257. bool isNull=false;
  258. args.bitStream->Read(isNull);
  259. if (isNull)
  260. {
  261. t=0;
  262. return IRC_SUCCESS;
  263. }
  264. typedef typename boost::remove_pointer< T >::type ActualObjectType;
  265. bool isArray=false;
  266. unsigned int count;
  267. args.bitStream->Read(isArray);
  268. if (isArray)
  269. args.bitStream->ReadCompressed(count);
  270. else
  271. count=1;
  272. t = new ActualObjectType[count]();
  273. if (isArray)
  274. {
  275. for (unsigned int i=0; i < count; i++)
  276. {
  277. DoRead< typename boost::remove_pointer<T>::type >::type::applyArray(* (args.bitStream),t+i);
  278. }
  279. }
  280. else
  281. {
  282. DoRead< typename boost::remove_pointer<T>::type >::type::apply(* (args.bitStream),t);
  283. }
  284. return IRC_SUCCESS;
  285. }
  286. template< typename T2 >
  287. static void Cleanup(T2 &t) {
  288. if (t)
  289. delete [] t;
  290. }
  291. };
  292. template< typename T >
  293. struct SetRPC3Ptr
  294. {
  295. static InvokeResultCodes apply(InvokeArgs &args, T &obj)
  296. {
  297. obj=args.caller;
  298. return IRC_SUCCESS;
  299. }
  300. //typedef boost::mpl::false_ Cleanup;
  301. template< typename T2 >
  302. static void Cleanup(T2 &t) {}
  303. };
  304. /*
  305. template< typename T >
  306. struct ReadWithNetworkID
  307. {
  308. typedef typename boost::mpl::if_<
  309. boost::is_pointer<T>
  310. , typename ReadWithNetworkIDPtr<T> // true
  311. , typename ReadWithNetworkIDNoPtr<T>
  312. >::type type;
  313. };
  314. */
  315. template< typename T >
  316. struct ReadWithoutNetworkID
  317. {
  318. typedef typename boost::mpl::if_<
  319. boost::is_pointer<T>
  320. , ReadWithoutNetworkIDPtr<T> // true
  321. , ReadWithoutNetworkIDNoPtr<T>
  322. >::type type;
  323. };
  324. template< typename T >
  325. struct identity
  326. {
  327. typedef T type;
  328. };
  329. template< typename T >
  330. struct IsRPC3Ptr
  331. {
  332. typedef typename boost::mpl::if_<
  333. boost::is_convertible<T,RPC3*>,
  334. boost::mpl::true_,
  335. boost::mpl::false_>::type type;
  336. };
  337. template< typename T >
  338. struct ShouldReadNetworkID
  339. {
  340. /*
  341. typedef typename boost::mpl::if_<
  342. boost::is_pointer<T>,
  343. typename identity<T>::type,
  344. boost::add_pointer<T>>::type typeWithPtr;
  345. typedef typename boost::mpl::if_<
  346. boost::is_convertible<typeWithPtr,NetworkIDObject*>,
  347. boost::mpl::true_,
  348. boost::mpl::false_>::type type;
  349. */
  350. typedef typename boost::mpl::if_<
  351. boost::is_convertible<T,NetworkIDObject*>,
  352. boost::mpl::true_,
  353. boost::mpl::false_>::type type;
  354. };
  355. template< typename T >
  356. struct GetReadFunction
  357. {
  358. /*
  359. typedef typename boost::mpl::if_<
  360. typename ShouldReadNetworkID<T>::type
  361. , typename ReadWithNetworkID<T>::type
  362. , typename ReadWithoutNetworkID<T>::type
  363. >::type type;
  364. */
  365. typedef typename boost::mpl::if_<
  366. typename ShouldReadNetworkID<T>::type
  367. , ReadWithNetworkIDPtr<T>
  368. , typename ReadWithoutNetworkID<T>::type
  369. >::type type;
  370. };
  371. template< typename T >
  372. struct ProcessArgType
  373. {
  374. typedef typename boost::mpl::if_<
  375. typename IsRPC3Ptr<T>::type
  376. , SetRPC3Ptr<T>
  377. , typename GetReadFunction<T>::type
  378. >::type type;
  379. };
  380. template< typename Function
  381. , class From = typename boost::mpl::begin< boost::function_types::parameter_types<Function> >::type
  382. , class To = typename boost::mpl::end< boost::function_types::parameter_types<Function> >::type
  383. >
  384. struct BoostRPCInvoker
  385. {
  386. // add an argument to a Fusion cons-list for each parameter type
  387. template<typename Args>
  388. static inline
  389. InvokeResultCodes apply(Function func, InvokeArgs &functionArgs, Args const &args)
  390. {
  391. typedef typename boost::mpl::deref<From>::type arg_type;
  392. typedef typename boost::mpl::next<From>::type next_iter_type;
  393. typedef typename boost::remove_reference<arg_type>::type arg_type_no_ref;
  394. arg_type_no_ref argType;
  395. ProcessArgType< arg_type_no_ref >::type::apply(functionArgs, argType);
  396. InvokeResultCodes irc = BoostRPCInvoker<Function, next_iter_type, To>::apply
  397. ( func, functionArgs, boost::fusion::push_back(args, boost::ref(argType) ) );
  398. ProcessArgType< arg_type_no_ref >::type::Cleanup(argType);
  399. return irc;
  400. }
  401. };
  402. template< typename Function
  403. , class From = typename boost::mpl::begin< boost::function_types::parameter_types<Function> >::type
  404. , class To = typename boost::mpl::end< boost::function_types::parameter_types<Function> >::type
  405. >
  406. struct BoostRPCInvoker_ThisPtr
  407. {
  408. // add an argument to a Fusion cons-list for each parameter type
  409. template<typename Args>
  410. static inline
  411. InvokeResultCodes apply(Function func, InvokeArgs &functionArgs, Args const &args)
  412. {
  413. typedef typename boost::mpl::deref<From>::type arg_type;
  414. typedef typename boost::mpl::next<From>::type next_iter_type;
  415. arg_type argType = (arg_type) *(functionArgs.thisPtr);
  416. return BoostRPCInvoker<Function, next_iter_type, To>::apply
  417. ( func, functionArgs, boost::fusion::push_back(args, boost::ref(argType) ) );
  418. }
  419. };
  420. template<typename Function, class To>
  421. struct BoostRPCInvoker<Function,To,To>
  422. {
  423. // the argument list is complete, now call the function
  424. template<typename Args>
  425. static inline
  426. InvokeResultCodes apply(Function func, InvokeArgs&, Args const &args)
  427. {
  428. boost::fusion::invoke(func,args);
  429. return IRC_SUCCESS;
  430. }
  431. };
  432. template <typename T>
  433. struct DoNothing
  434. {
  435. static void apply(RakNet::BitStream &bitStream, T& t)
  436. {
  437. (void) bitStream;
  438. (void) t;
  439. // printf("DoNothing\n");
  440. }
  441. };
  442. struct WriteBitstream
  443. {
  444. static void applyArray(RakNet::BitStream &bitStream, RakNet::BitStream* t) {apply(bitStream,t);}
  445. static void apply(RakNet::BitStream &bitStream, RakNet::BitStream* t)
  446. {
  447. BitSize_t oldReadOffset = t->GetReadOffset();
  448. t->ResetReadPointer();
  449. bitStream.WriteCompressed(t->GetNumberOfBitsUsed());
  450. bitStream.Write(t);
  451. t->SetReadOffset(oldReadOffset);
  452. }
  453. };
  454. //template <typename T>
  455. struct WritePtr
  456. {
  457. template <typename T2>
  458. static inline void applyArray(RakNet::BitStream &bitStream, T2 *t) {bitStream << (*t);}
  459. template <typename T2>
  460. static inline void apply(RakNet::BitStream &bitStream, T2 *t) {bitStream << (*t);}
  461. // template <>
  462. static inline void apply(RakNet::BitStream &bitStream, char *t) {bitStream << t;}
  463. // template <>
  464. static inline void apply(RakNet::BitStream &bitStream, unsigned char *t) {bitStream << t;}
  465. // template <>
  466. static inline void apply(RakNet::BitStream &bitStream, const char *t) {bitStream << t;}
  467. // template <>
  468. static inline void apply(RakNet::BitStream &bitStream, const unsigned char *t) {bitStream << t;}
  469. };
  470. template< typename T >
  471. struct DoWrite
  472. {
  473. typedef typename boost::mpl::if_<
  474. boost::is_convertible<T*,RakNet::BitStream*>,
  475. WriteBitstream,
  476. WritePtr >::type type;
  477. };
  478. template <typename T>
  479. struct WriteWithNetworkIDPtr
  480. {
  481. static void apply(RakNet::BitStream &bitStream, T& t)
  482. {
  483. bool isNull;
  484. isNull=(t==0);
  485. bitStream.Write(isNull);
  486. if (isNull)
  487. return;
  488. RPC3Tag tag;
  489. __RPC3ClearPtr(t, &tag);
  490. bool deref = (tag.flag & RPC3_TAG_FLAG_DEREF) !=0;
  491. bool isArray = (tag.flag & RPC3_TAG_FLAG_ARRAY) !=0;
  492. bitStream.Write(deref);
  493. bitStream.Write(isArray);
  494. if (isArray)
  495. {
  496. bitStream.WriteCompressed(tag.count);
  497. }
  498. for (unsigned int i=0; i < tag.count; i++)
  499. {
  500. NetworkID inNetworkID=t->GetNetworkID();
  501. bitStream << inNetworkID;
  502. if (deref)
  503. {
  504. // skip bytes, write data, go back, write number of bits written, reset cursor
  505. bitStream.AlignWriteToByteBoundary();
  506. BitSize_t writeOffset1 = bitStream.GetWriteOffset();
  507. BitSize_t bitsUsed1=bitStream.GetNumberOfBitsUsed();
  508. bitStream.Write(bitsUsed1);
  509. bitsUsed1=bitStream.GetNumberOfBitsUsed();
  510. DoWrite< typename boost::remove_pointer<T>::type >::type::apply(bitStream,t);
  511. BitSize_t writeOffset2 = bitStream.GetWriteOffset();
  512. BitSize_t bitsUsed2=bitStream.GetNumberOfBitsUsed();
  513. bitStream.SetWriteOffset(writeOffset1);
  514. bitStream.Write(bitsUsed2-bitsUsed1);
  515. bitStream.SetWriteOffset(writeOffset2);
  516. }
  517. }
  518. }
  519. };
  520. template <typename T>
  521. struct WriteWithoutNetworkIDNoPtr
  522. {
  523. static void apply(RakNet::BitStream &bitStream, T& t)
  524. {
  525. DoWrite< typename boost::remove_pointer<T>::type >::type::apply(bitStream,&t);
  526. }
  527. };
  528. template <typename T>
  529. struct WriteWithoutNetworkIDPtr
  530. {
  531. static void apply(RakNet::BitStream &bitStream, T& t)
  532. {
  533. bool isNull;
  534. isNull=(t==0);
  535. bitStream.Write(isNull);
  536. if (isNull)
  537. return;
  538. RPC3Tag tag;
  539. __RPC3ClearPtr((void*) t, &tag);
  540. bool isArray = (tag.flag & RPC3_TAG_FLAG_ARRAY) !=0;
  541. bitStream.Write(isArray);
  542. if (isArray)
  543. {
  544. bitStream.WriteCompressed(tag.count);
  545. }
  546. if (isArray)
  547. {
  548. for (unsigned int i=0; i < tag.count; i++)
  549. DoWrite< typename boost::remove_pointer<T>::type >::type::applyArray(bitStream,t+i);
  550. }
  551. else
  552. {
  553. DoWrite< typename boost::remove_pointer<T>::type >::type::apply(bitStream,t);
  554. }
  555. }
  556. };
  557. template <typename T>
  558. struct SerializeCallParameterBranch
  559. {
  560. typedef typename boost::mpl::if_<
  561. typename IsRPC3Ptr<T>::type
  562. , DoNothing<T>
  563. , WriteWithoutNetworkIDPtr<T>
  564. >::type typeCheck1;
  565. typedef typename boost::mpl::if_<
  566. boost::is_pointer<T>
  567. , typeCheck1
  568. , WriteWithoutNetworkIDNoPtr<T>
  569. >::type typeCheck2;
  570. typedef typename boost::mpl::if_<
  571. typename ShouldReadNetworkID<T>::type
  572. , WriteWithNetworkIDPtr<T>
  573. , typeCheck2
  574. >::type type;
  575. };
  576. template<typename Function>
  577. struct GetBoundPointer_C
  578. {
  579. // typedef typename GetBoundPointer_C type;
  580. static FunctionPointer GetBoundPointer(Function f)
  581. {
  582. return FunctionPointer(false, boost::bind( & BoostRPCInvoker<Function>::template apply<boost::fusion::nil>, f, _1, boost::fusion::nil() ));
  583. }
  584. };
  585. template<typename Function>
  586. struct GetBoundPointer_CPP
  587. {
  588. // typedef typename GetBoundPointer_CPP type;
  589. static FunctionPointer GetBoundPointer(Function f)
  590. {
  591. return FunctionPointer(true, boost::bind( & BoostRPCInvoker_ThisPtr<Function>::template apply<boost::fusion::nil>, f, _1, boost::fusion::nil() ));
  592. }
  593. };
  594. template<typename Function>
  595. FunctionPointer GetBoundPointer(Function f)
  596. {
  597. return boost::mpl::if_<
  598. boost::is_member_function_pointer<Function>
  599. , GetBoundPointer_CPP<Function>
  600. , GetBoundPointer_C<Function>
  601. >::type::GetBoundPointer(f);
  602. // return FunctionPointer(true, boost::bind( & BoostRPCInvoker<Function>::template apply<boost::fusion::nil>, f, _1, boost::fusion::nil() ) );
  603. }
  604. }
  605. }
  606. #endif
粤ICP备19079148号