PageRenderTime 61ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Assets/LUA/NLua/GenerateEventAssembly/CodeGeneration.cs

https://bitbucket.org/rusoaica/judgement-day-map-editor
C# | 626 lines | 574 code | 18 blank | 34 comment | 79 complexity | ffebd9afecb52c47243cd31de0a7a17e MD5 | raw file
  1. using System;
  2. using System.Threading;
  3. using System.Reflection;
  4. #if !MONOTOUCH
  5. using System.Reflection.Emit;
  6. #endif
  7. using System.Collections.Generic;
  8. using NLua.Method;
  9. namespace NLua
  10. {
  11. class CodeGeneration
  12. {
  13. private Dictionary<Type, LuaClassType> _classCollection = new Dictionary<Type, LuaClassType>();
  14. private Dictionary<Type, Type> _delegateCollection = new Dictionary<Type, Type>();
  15. private static readonly CodeGeneration _instance = new CodeGeneration();
  16. private AssemblyName _assemblyName;
  17. #if !MONOTOUCH && !SILVERLIGHT
  18. private Dictionary<Type, Type> _eventHandlerCollection = new Dictionary<Type, Type>();
  19. private Type _eventHandlerParent = typeof(LuaEventHandler);
  20. private Type _delegateParent = typeof(LuaDelegate);
  21. private Type _classHelper = typeof(LuaClassHelper);
  22. private AssemblyBuilder _newAssembly;
  23. private ModuleBuilder _newModule;
  24. private int _luaClassNumber = 1;
  25. #endif
  26. static CodeGeneration() { }
  27. private CodeGeneration()
  28. {
  29. _assemblyName = new AssemblyName();
  30. _assemblyName.Name = "NLua_generatedcode";
  31. #if !MONOTOUCH && !SILVERLIGHT
  32. _newAssembly = Thread.GetDomain().DefineDynamicAssembly(_assemblyName, AssemblyBuilderAccess.Run);
  33. _newModule = _newAssembly.DefineDynamicModule("NLua_generatedcode");
  34. #endif
  35. }
  36. /*
  37. * Singleton instance of the class
  38. */
  39. public static CodeGeneration Instance
  40. {
  41. get { return _instance; }
  42. }
  43. /*
  44. * Generates an event handler that calls a Lua function
  45. */
  46. private Type GenerateEvent(Type _event_handler_type)
  47. {
  48. #if MONOTOUCH
  49. throw new NotImplementedException (" Emit not available on MonoTouch ");
  50. #elif SILVERLIGHT
  51. throw new NotImplementedException(" Emit not available on Silverlight ");
  52. #else
  53. string _type_name;
  54. lock (this)
  55. {
  56. _type_name = "LuaGeneratedClass" + _luaClassNumber.ToString();
  57. _luaClassNumber++;
  58. }
  59. var _my_type = _newModule.DefineType(_type_name, TypeAttributes.Public, _eventHandlerParent);
  60. var _param_types = new Type[2];
  61. _param_types[0] = typeof(object);
  62. _param_types[1] = _event_handler_type;
  63. var _return_type = typeof(void);
  64. var _handle_method = _my_type.DefineMethod("HandleEvent", MethodAttributes.Public | MethodAttributes.HideBySig, _return_type, _param_types);
  65. ILGenerator _generator = _handle_method.GetILGenerator();
  66. _generator.Emit(OpCodes.Ldarg_0);
  67. _generator.Emit(OpCodes.Ldarg_1);
  68. _generator.Emit(OpCodes.Ldarg_2);
  69. var _mi_generic_event_handler = _eventHandlerParent.GetMethod("HandleEvent");
  70. _generator.Emit(OpCodes.Call, _mi_generic_event_handler);
  71. _generator.Emit(OpCodes.Ret);
  72. return _my_type.CreateType();
  73. #endif
  74. }
  75. /*
  76. * Generates a type that can be used for instantiating a delegate
  77. * of the provided type, given a Lua function.
  78. */
  79. private Type GenerateDelegate(Type _delegate_type)
  80. {
  81. #if MONOTOUCH
  82. throw new NotImplementedException ("GenerateDelegate is not available on iOS, please register your LuaDelegate type with Lua.RegisterLuaDelegateType( yourDelegate, theLuaDelegateHandler) ");
  83. #elif SILVERLIGHT
  84. throw new NotImplementedException("GenerateDelegate is not available on Silverlight, please register your LuaDelegate type with Lua.RegisterLuaDelegateType( yourDelegate, theLuaDelegateHandler) ");
  85. #else
  86. string _type_name;
  87. lock (this)
  88. {
  89. _type_name = "LuaGeneratedClass" + _luaClassNumber.ToString();
  90. _luaClassNumber++;
  91. }
  92. var _my_type = _newModule.DefineType(_type_name, TypeAttributes.Public, _delegateParent);
  93. var _invoke_method = _delegate_type.GetMethod("Invoke");
  94. var _param_info = _invoke_method.GetParameters();
  95. var _param_types = new Type[_param_info.Length];
  96. var _return_type = _invoke_method.ReturnType;
  97. int _n_out_params = 0;
  98. int _n_out_and_ref_params = 0;
  99. for (int i = 0; i < _param_types.Length; i++)
  100. {
  101. _param_types[i] = _param_info[i].ParameterType;
  102. if ((!_param_info[i].IsIn) && _param_info[i].IsOut)
  103. _n_out_params++;
  104. if (_param_types[i].IsByRef)
  105. _n_out_and_ref_params++;
  106. }
  107. int[] _ref_args = new int[_n_out_and_ref_params];
  108. var _delegate_method = _my_type.DefineMethod("CallFunction", _invoke_method.Attributes, _return_type, _param_types);
  109. ILGenerator _generator = _delegate_method.GetILGenerator();
  110. _generator.DeclareLocal(typeof(object[]));
  111. _generator.DeclareLocal(typeof(object[]));
  112. _generator.DeclareLocal(typeof(int[]));
  113. if (!(_return_type == typeof(void)))
  114. _generator.DeclareLocal(_return_type);
  115. else
  116. _generator.DeclareLocal(typeof(object));
  117. _generator.Emit(OpCodes.Ldc_I4, _param_types.Length);
  118. _generator.Emit(OpCodes.Newarr, typeof(object));
  119. _generator.Emit(OpCodes.Stloc_0);
  120. _generator.Emit(OpCodes.Ldc_I4, _param_types.Length - _n_out_params);
  121. _generator.Emit(OpCodes.Newarr, typeof(object));
  122. _generator.Emit(OpCodes.Stloc_1);
  123. _generator.Emit(OpCodes.Ldc_I4, _n_out_and_ref_params);
  124. _generator.Emit(OpCodes.Newarr, typeof(int));
  125. _generator.Emit(OpCodes.Stloc_2);
  126. for (int _i_args = 0, _i_in_args = 0, _i_out_args = 0; _i_args < _param_types.Length; _i_args++)
  127. {
  128. _generator.Emit(OpCodes.Ldloc_0);
  129. _generator.Emit(OpCodes.Ldc_I4, _i_args);
  130. _generator.Emit(OpCodes.Ldarg, _i_args + 1);
  131. if (_param_types[_i_args].IsByRef)
  132. {
  133. if (_param_types[_i_args].GetElementType().IsValueType)
  134. {
  135. _generator.Emit(OpCodes.Ldobj, _param_types[_i_args].GetElementType());
  136. _generator.Emit(OpCodes.Box, _param_types[_i_args].GetElementType());
  137. }
  138. else
  139. _generator.Emit(OpCodes.Ldind_Ref);
  140. }
  141. else
  142. {
  143. if (_param_types[_i_args].IsValueType)
  144. _generator.Emit(OpCodes.Box, _param_types[_i_args]);
  145. }
  146. _generator.Emit(OpCodes.Stelem_Ref);
  147. if (_param_types[_i_args].IsByRef)
  148. {
  149. _generator.Emit(OpCodes.Ldloc_2);
  150. _generator.Emit(OpCodes.Ldc_I4, _i_out_args);
  151. _generator.Emit(OpCodes.Ldc_I4, _i_args);
  152. _generator.Emit(OpCodes.Stelem_I4);
  153. _ref_args[_i_out_args] = _i_args;
  154. _i_out_args++;
  155. }
  156. if (_param_info[_i_args].IsIn || (!_param_info[_i_args].IsOut))
  157. {
  158. _generator.Emit(OpCodes.Ldloc_1);
  159. _generator.Emit(OpCodes.Ldc_I4, _i_in_args);
  160. _generator.Emit(OpCodes.Ldarg, _i_args + 1);
  161. if (_param_types[_i_args].IsByRef)
  162. {
  163. if (_param_types[_i_args].GetElementType().IsValueType)
  164. {
  165. _generator.Emit(OpCodes.Ldobj, _param_types[_i_args].GetElementType());
  166. _generator.Emit(OpCodes.Box, _param_types[_i_args].GetElementType());
  167. }
  168. else
  169. _generator.Emit(OpCodes.Ldind_Ref);
  170. }
  171. else
  172. {
  173. if (_param_types[_i_args].IsValueType)
  174. _generator.Emit(OpCodes.Box, _param_types[_i_args]);
  175. }
  176. _generator.Emit(OpCodes.Stelem_Ref);
  177. _i_in_args++;
  178. }
  179. }
  180. _generator.Emit(OpCodes.Ldarg_0);
  181. _generator.Emit(OpCodes.Ldloc_0);
  182. _generator.Emit(OpCodes.Ldloc_1);
  183. _generator.Emit(OpCodes.Ldloc_2);
  184. var _mi_generic_event_handler = _delegateParent.GetMethod("CallFunction");
  185. _generator.Emit(OpCodes.Call, _mi_generic_event_handler);
  186. if (_return_type == typeof(void))
  187. {
  188. _generator.Emit(OpCodes.Pop);
  189. _generator.Emit(OpCodes.Ldnull);
  190. }
  191. else if (_return_type.IsValueType)
  192. {
  193. _generator.Emit(OpCodes.Unbox, _return_type);
  194. _generator.Emit(OpCodes.Ldobj, _return_type);
  195. }
  196. else
  197. _generator.Emit(OpCodes.Castclass, _return_type);
  198. _generator.Emit(OpCodes.Stloc_3);
  199. for (int i = 0; i < _ref_args.Length; i++)
  200. {
  201. _generator.Emit(OpCodes.Ldarg, _ref_args[i] + 1);
  202. _generator.Emit(OpCodes.Ldloc_0);
  203. _generator.Emit(OpCodes.Ldc_I4, _ref_args[i]);
  204. _generator.Emit(OpCodes.Ldelem_Ref);
  205. if (_param_types[_ref_args[i]].GetElementType().IsValueType)
  206. {
  207. _generator.Emit(OpCodes.Unbox, _param_types[_ref_args[i]].GetElementType());
  208. _generator.Emit(OpCodes.Ldobj, _param_types[_ref_args[i]].GetElementType());
  209. _generator.Emit(OpCodes.Stobj, _param_types[_ref_args[i]].GetElementType());
  210. }
  211. else
  212. {
  213. _generator.Emit(OpCodes.Castclass, _param_types[_ref_args[i]].GetElementType());
  214. _generator.Emit(OpCodes.Stind_Ref);
  215. }
  216. }
  217. if (!(_return_type == typeof(void)))
  218. _generator.Emit(OpCodes.Ldloc_3);
  219. _generator.Emit(OpCodes.Ret);
  220. return _my_type.CreateType();
  221. #endif
  222. }
  223. void GetReturnTypesFromClass(Type _class, out Type[][] _return_types)
  224. {
  225. var _class_methods = _class.GetMethods();
  226. _return_types = new Type[_class_methods.Length][];
  227. int i = 0;
  228. foreach (var _method in _class_methods)
  229. {
  230. if (_class.IsInterface)
  231. {
  232. GetReturnTypesFromMethod(_method, out _return_types[i]);
  233. i++;
  234. }
  235. else
  236. {
  237. if (!_method.IsPrivate && !_method.IsFinal && _method.IsVirtual)
  238. {
  239. GetReturnTypesFromMethod(_method, out _return_types[i]);
  240. i++;
  241. }
  242. }
  243. }
  244. }
  245. /*
  246. * Generates an implementation of klass, if it is an interface, or
  247. * a subclass of klass that delegates its virtual methods to a Lua table.
  248. */
  249. public void GenerateClass(Type _class, out Type _new_type, out Type[][] _return_types)
  250. {
  251. #if MONOTOUCH
  252. throw new NotImplementedException (" Emit not available on MonoTouch ");
  253. #elif SILVERLIGHT
  254. throw new NotImplementedException (" Emit not available on Silverlight ");
  255. #else
  256. string _type_name;
  257. lock (this)
  258. {
  259. _type_name = "LuaGeneratedClass" + _luaClassNumber.ToString();
  260. _luaClassNumber++;
  261. }
  262. TypeBuilder _my_type;
  263. if (_class.IsInterface)
  264. _my_type = _newModule.DefineType(_type_name, TypeAttributes.Public, typeof(object), new Type[] { _class, typeof(ILuaGeneratedType) });
  265. else
  266. _my_type = _newModule.DefineType(_type_name, TypeAttributes.Public, _class, new Type[] { typeof(ILuaGeneratedType) });
  267. var _lua_table_field = _my_type.DefineField("__luaInterface_luaTable", typeof(LuaTable), FieldAttributes.Public);
  268. var _return_types_field = _my_type.DefineField("__luaInterface_returnTypes", typeof(Type[][]), FieldAttributes.Public);
  269. var _constructor = _my_type.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(LuaTable), typeof(Type[][]) });
  270. ILGenerator _generator = _constructor.GetILGenerator();
  271. _generator.Emit(OpCodes.Ldarg_0);
  272. if (_class.IsInterface)
  273. _generator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
  274. else
  275. _generator.Emit(OpCodes.Call, _class.GetConstructor(Type.EmptyTypes));
  276. _generator.Emit(OpCodes.Ldarg_0);
  277. _generator.Emit(OpCodes.Ldarg_1);
  278. _generator.Emit(OpCodes.Stfld, _lua_table_field);
  279. _generator.Emit(OpCodes.Ldarg_0);
  280. _generator.Emit(OpCodes.Ldarg_2);
  281. _generator.Emit(OpCodes.Stfld, _return_types_field);
  282. _generator.Emit(OpCodes.Ret);
  283. var _class_methods = _class.GetMethods();
  284. _return_types = new Type[_class_methods.Length][];
  285. int i = 0;
  286. foreach (var _method in _class_methods)
  287. {
  288. if (_class.IsInterface)
  289. {
  290. GenerateMethod(_my_type, _method, MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot, i, _lua_table_field, _return_types_field, false, out _return_types[i]);
  291. i++;
  292. }
  293. else
  294. {
  295. if (!_method.IsPrivate && !_method.IsFinal && _method.IsVirtual)
  296. {
  297. GenerateMethod(_my_type, _method, (_method.Attributes | MethodAttributes.NewSlot) ^ MethodAttributes.NewSlot, i, _lua_table_field, _return_types_field, true, out _return_types[i]);
  298. i++;
  299. }
  300. }
  301. }
  302. var _return_table_method = _my_type.DefineMethod("LuaInterfaceGetLuaTable", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(LuaTable), new Type[0]);
  303. _my_type.DefineMethodOverride(_return_table_method, typeof(ILuaGeneratedType).GetMethod("LuaInterfaceGetLuaTable"));
  304. _generator = _return_table_method.GetILGenerator();
  305. _generator.Emit(OpCodes.Ldfld, _lua_table_field);
  306. _generator.Emit(OpCodes.Ret);
  307. _new_type = _my_type.CreateType();
  308. #endif
  309. }
  310. void GetReturnTypesFromMethod(MethodInfo _method, out Type[] _return_types)
  311. {
  312. var _param_info = _method.GetParameters();
  313. var _param_types = new Type[_param_info.Length];
  314. var _return_types_list = new List<Type>();
  315. int _n_out_params = 0;
  316. int _n_out_and_ref_params = 0;
  317. var _return_type = _method.ReturnType;
  318. _return_types_list.Add(_return_type);
  319. for (int i = 0; i < _param_types.Length; i++)
  320. {
  321. _param_types[i] = _param_info[i].ParameterType;
  322. #if SILVERLIGHT
  323. if (_param_info[i].IsOut)
  324. #else
  325. if ((!_param_info[i].IsIn) && _param_info[i].IsOut)
  326. #endif
  327. _n_out_params++;
  328. if (_param_types[i].IsByRef)
  329. {
  330. _return_types_list.Add(_param_types[i].GetElementType());
  331. _n_out_and_ref_params++;
  332. }
  333. }
  334. _return_types = _return_types_list.ToArray();
  335. }
  336. #if !MONOTOUCH && !SILVERLIGHT
  337. /*
  338. * Generates an overriden implementation of method inside myType that delegates
  339. * to a function in a Lua table with the same name, if the function exists. If it
  340. * doesn't the method calls the base method (or does nothing, in case of interface
  341. * implementations).
  342. */
  343. private void GenerateMethod(TypeBuilder _my_type, MethodInfo _method, MethodAttributes _attributes, int _method_index, FieldInfo _lua_table_field, FieldInfo _return_types_field, bool _generate_base, out Type[] _return_types)
  344. {
  345. var _param_info = _method.GetParameters();
  346. var _param_types = new Type[_param_info.Length];
  347. var _return_types_list = new List<Type>();
  348. int _n_out_params = 0;
  349. int _n_out_and_ref_params = 0;
  350. var _return_type = _method.ReturnType;
  351. _return_types_list.Add(_return_type);
  352. for (int i = 0; i < _param_types.Length; i++)
  353. {
  354. _param_types[i] = _param_info[i].ParameterType;
  355. if ((!_param_info[i].IsIn) && _param_info[i].IsOut)
  356. _n_out_params++;
  357. if (_param_types[i].IsByRef)
  358. {
  359. _return_types_list.Add(_param_types[i].GetElementType());
  360. _n_out_and_ref_params++;
  361. }
  362. }
  363. int[] _ref_args = new int[_n_out_and_ref_params];
  364. _return_types = _return_types_list.ToArray();
  365. if (_generate_base)
  366. {
  367. var _base_method = _my_type.DefineMethod("__luaInterface_base_" + _method.Name, MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.HideBySig, _return_type, _param_types);
  368. ILGenerator _generator_base = _base_method.GetILGenerator();
  369. _generator_base.Emit(OpCodes.Ldarg_0);
  370. for (int i = 0; i < _param_types.Length; i++)
  371. _generator_base.Emit(OpCodes.Ldarg, i + 1);
  372. _generator_base.Emit(OpCodes.Call, _method);
  373. if (_return_type == typeof(void))
  374. _generator_base.Emit(OpCodes.Pop);
  375. _generator_base.Emit(OpCodes.Ret);
  376. }
  377. var _method_impl = _my_type.DefineMethod(_method.Name, _attributes, _return_type, _param_types);
  378. if (_my_type.BaseType.Equals(typeof(object)))
  379. _my_type.DefineMethodOverride(_method_impl, _method);
  380. ILGenerator _generator = _method_impl.GetILGenerator();
  381. _generator.DeclareLocal(typeof(object[]));
  382. _generator.DeclareLocal(typeof(object[]));
  383. _generator.DeclareLocal(typeof(int[]));
  384. if (!(_return_type == typeof(void)))
  385. _generator.DeclareLocal(_return_type);
  386. else
  387. _generator.DeclareLocal(typeof(object));
  388. _generator.Emit(OpCodes.Ldc_I4, _param_types.Length);
  389. _generator.Emit(OpCodes.Newarr, typeof(object));
  390. _generator.Emit(OpCodes.Stloc_0);
  391. _generator.Emit(OpCodes.Ldc_I4, _param_types.Length - _n_out_params + 1);
  392. _generator.Emit(OpCodes.Newarr, typeof(object));
  393. _generator.Emit(OpCodes.Stloc_1);
  394. _generator.Emit(OpCodes.Ldc_I4, _n_out_and_ref_params);
  395. _generator.Emit(OpCodes.Newarr, typeof(int));
  396. _generator.Emit(OpCodes.Stloc_2);
  397. _generator.Emit(OpCodes.Ldloc_1);
  398. _generator.Emit(OpCodes.Ldc_I4_0);
  399. _generator.Emit(OpCodes.Ldarg_0);
  400. _generator.Emit(OpCodes.Ldfld, _lua_table_field);
  401. _generator.Emit(OpCodes.Stelem_Ref);
  402. for (int _i_args = 0, _i_in_args = 1, _i_out_args = 0; _i_args < _param_types.Length; _i_args++)
  403. {
  404. _generator.Emit(OpCodes.Ldloc_0);
  405. _generator.Emit(OpCodes.Ldc_I4, _i_args);
  406. _generator.Emit(OpCodes.Ldarg, _i_args + 1);
  407. if (_param_types[_i_args].IsByRef)
  408. {
  409. if (_param_types[_i_args].GetElementType().IsValueType)
  410. {
  411. _generator.Emit(OpCodes.Ldobj, _param_types[_i_args].GetElementType());
  412. _generator.Emit(OpCodes.Box, _param_types[_i_args].GetElementType());
  413. }
  414. else
  415. _generator.Emit(OpCodes.Ldind_Ref);
  416. }
  417. else
  418. {
  419. if (_param_types[_i_args].IsValueType)
  420. _generator.Emit(OpCodes.Box, _param_types[_i_args]);
  421. }
  422. _generator.Emit(OpCodes.Stelem_Ref);
  423. if (_param_types[_i_args].IsByRef)
  424. {
  425. _generator.Emit(OpCodes.Ldloc_2);
  426. _generator.Emit(OpCodes.Ldc_I4, _i_out_args);
  427. _generator.Emit(OpCodes.Ldc_I4, _i_args);
  428. _generator.Emit(OpCodes.Stelem_I4);
  429. _ref_args[_i_out_args] = _i_args;
  430. _i_out_args++;
  431. }
  432. if (_param_info[_i_args].IsIn || (!_param_info[_i_args].IsOut))
  433. {
  434. _generator.Emit(OpCodes.Ldloc_1);
  435. _generator.Emit(OpCodes.Ldc_I4, _i_in_args);
  436. _generator.Emit(OpCodes.Ldarg, _i_args + 1);
  437. if (_param_types[_i_args].IsByRef)
  438. {
  439. if (_param_types[_i_args].GetElementType().IsValueType)
  440. {
  441. _generator.Emit(OpCodes.Ldobj, _param_types[_i_args].GetElementType());
  442. _generator.Emit(OpCodes.Box, _param_types[_i_args].GetElementType());
  443. }
  444. else
  445. _generator.Emit(OpCodes.Ldind_Ref);
  446. }
  447. else
  448. {
  449. if (_param_types[_i_args].IsValueType)
  450. _generator.Emit(OpCodes.Box, _param_types[_i_args]);
  451. }
  452. _generator.Emit(OpCodes.Stelem_Ref);
  453. _i_in_args++;
  454. }
  455. }
  456. _generator.Emit(OpCodes.Ldarg_0);
  457. _generator.Emit(OpCodes.Ldfld, _lua_table_field);
  458. _generator.Emit(OpCodes.Ldstr, _method.Name);
  459. _generator.Emit(OpCodes.Call, _classHelper.GetMethod("GetTableFunction"));
  460. var _lab_1 = _generator.DefineLabel();
  461. _generator.Emit(OpCodes.Dup);
  462. _generator.Emit(OpCodes.Brtrue_S, _lab_1);
  463. _generator.Emit(OpCodes.Pop);
  464. if (!_method.IsAbstract)
  465. {
  466. _generator.Emit(OpCodes.Ldarg_0);
  467. for (int i = 0; i < _param_types.Length; i++)
  468. _generator.Emit(OpCodes.Ldarg, i + 1);
  469. _generator.Emit(OpCodes.Call, _method);
  470. if (_return_type == typeof(void))
  471. _generator.Emit(OpCodes.Pop);
  472. _generator.Emit(OpCodes.Ret);
  473. _generator.Emit(OpCodes.Ldnull);
  474. }
  475. else
  476. _generator.Emit(OpCodes.Ldnull);
  477. var _lab_2 = _generator.DefineLabel();
  478. _generator.Emit(OpCodes.Br_S, _lab_2);
  479. _generator.MarkLabel(_lab_1);
  480. _generator.Emit(OpCodes.Ldloc_0);
  481. _generator.Emit(OpCodes.Ldarg_0);
  482. _generator.Emit(OpCodes.Ldfld, _return_types_field);
  483. _generator.Emit(OpCodes.Ldc_I4, _method_index);
  484. _generator.Emit(OpCodes.Ldelem_Ref);
  485. _generator.Emit(OpCodes.Ldloc_1);
  486. _generator.Emit(OpCodes.Ldloc_2);
  487. _generator.Emit(OpCodes.Call, _classHelper.GetMethod("CallFunction"));
  488. _generator.MarkLabel(_lab_2);
  489. if (_return_type == typeof(void))
  490. {
  491. _generator.Emit(OpCodes.Pop);
  492. _generator.Emit(OpCodes.Ldnull);
  493. }
  494. else if (_return_type.IsValueType)
  495. {
  496. _generator.Emit(OpCodes.Unbox, _return_type);
  497. _generator.Emit(OpCodes.Ldobj, _return_type);
  498. }
  499. else
  500. _generator.Emit(OpCodes.Castclass, _return_type);
  501. _generator.Emit(OpCodes.Stloc_3);
  502. for (int i = 0; i < _ref_args.Length; i++)
  503. {
  504. _generator.Emit(OpCodes.Ldarg, _ref_args[i] + 1);
  505. _generator.Emit(OpCodes.Ldloc_0);
  506. _generator.Emit(OpCodes.Ldc_I4, _ref_args[i]);
  507. _generator.Emit(OpCodes.Ldelem_Ref);
  508. if (_param_types[_ref_args[i]].GetElementType().IsValueType)
  509. {
  510. _generator.Emit(OpCodes.Unbox, _param_types[_ref_args[i]].GetElementType());
  511. _generator.Emit(OpCodes.Ldobj, _param_types[_ref_args[i]].GetElementType());
  512. _generator.Emit(OpCodes.Stobj, _param_types[_ref_args[i]].GetElementType());
  513. }
  514. else
  515. {
  516. _generator.Emit(OpCodes.Castclass, _param_types[_ref_args[i]].GetElementType());
  517. _generator.Emit(OpCodes.Stind_Ref);
  518. }
  519. }
  520. if (!(_return_type == typeof(void)))
  521. _generator.Emit(OpCodes.Ldloc_3);
  522. _generator.Emit(OpCodes.Ret);
  523. }
  524. #endif
  525. /*
  526. * Gets an event handler for the event type that delegates to the eventHandler Lua function.
  527. * Caches the generated type.
  528. */
  529. public LuaEventHandler GetEvent(Type _event_handler_type, LuaFunction _event_handler)
  530. {
  531. #if MONOTOUCH
  532. throw new NotImplementedException (" Emit not available on MonoTouch ");
  533. #elif SILVERLIGHT
  534. throw new NotImplementedException (" Emit not available on Silverlight ");
  535. #else
  536. Type _event_consumer_type;
  537. if (_eventHandlerCollection.ContainsKey(_event_handler_type))
  538. _event_consumer_type = _eventHandlerCollection[_event_handler_type];
  539. else
  540. {
  541. _event_consumer_type = GenerateEvent(_event_handler_type);
  542. _eventHandlerCollection[_event_handler_type] = _event_consumer_type;
  543. }
  544. var _lua_event_handler = (LuaEventHandler)Activator.CreateInstance(_event_consumer_type);
  545. _lua_event_handler.handler = _event_handler;
  546. return _lua_event_handler;
  547. #endif
  548. }
  549. public void RegisterLuaDelegateType(Type _delegate_type, Type _lua_delegate_type)
  550. {
  551. _delegateCollection[_delegate_type] = _lua_delegate_type;
  552. }
  553. public void RegisterLuaClassType(Type _class, Type _lua_class)
  554. {
  555. LuaClassType _lua_class_type = new LuaClassType();
  556. _lua_class_type.klass = _lua_class;
  557. GetReturnTypesFromClass(_class, out _lua_class_type.returnTypes);
  558. _classCollection[_class] = _lua_class_type;
  559. }
  560. /*
  561. * Gets a delegate with delegateType that calls the luaFunc Lua function
  562. * Caches the generated type.
  563. */
  564. public Delegate GetDelegate(Type _delegate_type, LuaFunction _lua_func)
  565. {
  566. var _return_types = new List<Type>();
  567. Type _lua_delegate_type;
  568. if (_delegateCollection.ContainsKey(_delegate_type))
  569. _lua_delegate_type = _delegateCollection[_delegate_type];
  570. else
  571. {
  572. _lua_delegate_type = GenerateDelegate(_delegate_type);
  573. _delegateCollection[_delegate_type] = _lua_delegate_type;
  574. }
  575. var _method_info = _delegate_type.GetMethod("Invoke");
  576. _return_types.Add(_method_info.ReturnType);
  577. foreach (ParameterInfo _param_info in _method_info.GetParameters())
  578. if (_param_info.ParameterType.IsByRef)
  579. _return_types.Add(_param_info.ParameterType);
  580. var _lua_delegate = (LuaDelegate)Activator.CreateInstance(_lua_delegate_type);
  581. _lua_delegate.function = _lua_func;
  582. _lua_delegate.returnTypes = _return_types.ToArray();
  583. return Delegate.CreateDelegate(_delegate_type, _lua_delegate, "CallFunction");
  584. }
  585. /*
  586. * Gets an instance of an implementation of the klass interface or
  587. * subclass of klass that delegates public virtual methods to the
  588. * luaTable table.
  589. * Caches the generated type.
  590. */
  591. public object GetClassInstance(Type _class, LuaTable _lua_table)
  592. {
  593. LuaClassType _lua_class_type;
  594. if (_classCollection.ContainsKey(_class))
  595. _lua_class_type = _classCollection[_class];
  596. else
  597. {
  598. _lua_class_type = new LuaClassType();
  599. GenerateClass(_class, out _lua_class_type.klass, out _lua_class_type.returnTypes);
  600. _classCollection[_class] = _lua_class_type;
  601. }
  602. return Activator.CreateInstance(_lua_class_type.klass, new object[] {
  603. _lua_table,
  604. _lua_class_type.returnTypes
  605. });
  606. }
  607. }
  608. }