pocketpy.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using UnityEngine;
  4. namespace pkpy
  5. {
  6. public static class Bindings
  7. {
  8. #if UNITY_IOS
  9. private const string _libName = "__Internal";
  10. #else
  11. private const string _libName = "pocketpy";
  12. #endif
  13. [DllImport(_libName)]
  14. internal static extern void pkpy_delete(IntPtr p);
  15. [DllImport(_libName)]
  16. internal static extern IntPtr pkpy_new_repl(IntPtr vm);
  17. [DllImport(_libName)]
  18. internal static extern int pkpy_repl_input(IntPtr r, string line);
  19. [DllImport(_libName)]
  20. internal static extern IntPtr pkpy_new_tvm(bool use_stdio);
  21. [DllImport(_libName)]
  22. internal static extern bool pkpy_tvm_exec_async(IntPtr vm, string source);
  23. [DllImport(_libName)]
  24. internal static extern int pkpy_tvm_get_state(IntPtr vm);
  25. [DllImport(_libName)]
  26. internal static extern string pkpy_tvm_read_jsonrpc_request(IntPtr vm);
  27. [DllImport(_libName)]
  28. internal static extern void pkpy_tvm_reset_state(IntPtr vm);
  29. [DllImport(_libName)]
  30. internal static extern void pkpy_tvm_terminate(IntPtr vm);
  31. [DllImport(_libName)]
  32. internal static extern void pkpy_tvm_write_jsonrpc_response(IntPtr vm, string value);
  33. [DllImport(_libName)]
  34. internal static extern IntPtr pkpy_new_vm(bool use_stdio);
  35. [DllImport(_libName)]
  36. internal static extern bool pkpy_vm_add_module(IntPtr vm, string name, string source);
  37. [DllImport(_libName)]
  38. internal static extern string pkpy_vm_eval(IntPtr vm, string source);
  39. [DllImport(_libName)]
  40. internal static extern bool pkpy_vm_exec(IntPtr vm, string source);
  41. [DllImport(_libName)]
  42. internal static extern string pkpy_vm_get_global(IntPtr vm, string name);
  43. [DllImport(_libName)]
  44. internal static extern string pkpy_vm_read_output(IntPtr vm);
  45. }
  46. }
  47. namespace pkpy
  48. {
  49. public struct PyOutput
  50. {
  51. public string stdout;
  52. public string stderr;
  53. public PyOutput(string stdout, string stderr)
  54. {
  55. this.stdout = stdout;
  56. this.stderr = stderr;
  57. }
  58. }
  59. public class VM
  60. {
  61. public IntPtr pointer { get; private set; }
  62. public VM()
  63. {
  64. if(this is ThreadedVM)
  65. {
  66. pointer = Bindings.pkpy_new_tvm(false);
  67. }
  68. else
  69. {
  70. pointer = Bindings.pkpy_new_vm(false);
  71. }
  72. }
  73. public PyOutput read_output()
  74. {
  75. var _o = Bindings.pkpy_vm_read_output(pointer);
  76. return JsonUtility.FromJson<PyOutput>(_o);
  77. }
  78. public void dispose()
  79. {
  80. Bindings.pkpy_delete(pointer);
  81. }
  82. /// <summary>
  83. /// Add a source module into a virtual machine. Return `true` if there is no complie error.
  84. /// </summary>
  85. public bool add_module(string name, string source)
  86. {
  87. return Bindings.pkpy_vm_add_module(pointer, name, source);
  88. }
  89. /// <summary>
  90. /// Evaluate an expression. Return a json representing the result. If there is any error, return `nullptr`.
  91. /// </summary>
  92. public string eval(string source)
  93. {
  94. return Bindings.pkpy_vm_eval(pointer, source);
  95. }
  96. /// <summary>
  97. /// Run a given source on a virtual machine. Return `true` if there is no compile error.
  98. /// </summary>
  99. public bool exec(string source)
  100. {
  101. return Bindings.pkpy_vm_exec(pointer, source);
  102. }
  103. /// <summary>
  104. /// Get a global variable of a virtual machine. Return a json representing the result. If the variable is not found, return `nullptr`.
  105. /// </summary>
  106. public string get_global(string name)
  107. {
  108. return Bindings.pkpy_vm_get_global(pointer, name);
  109. }
  110. }
  111. public enum ThreadState
  112. {
  113. ready = 0,
  114. running,
  115. suspended,
  116. finished
  117. }
  118. public class ThreadedVM : VM
  119. {
  120. public ThreadState state => (ThreadState)Bindings.pkpy_tvm_get_state(pointer);
  121. /// <summary>
  122. /// Run a given source on a threaded virtual machine. The excution will be started in a new thread. Return `true` if there is no compile error.
  123. /// </summary>
  124. public bool exec_async(string source)
  125. {
  126. return Bindings.pkpy_tvm_exec_async(pointer, source);
  127. }
  128. /// <summary>
  129. /// Read the current JSONRPC request from shared string buffer.
  130. /// </summary>
  131. public string read_jsonrpc_request()
  132. {
  133. return Bindings.pkpy_tvm_read_jsonrpc_request(pointer);
  134. }
  135. /// <summary>
  136. /// Set the state of a threaded virtual machine to `THREAD_READY`. The current state should be `THREAD_FINISHED`.
  137. /// </summary>
  138. public void reset_state()
  139. {
  140. Bindings.pkpy_tvm_reset_state(pointer);
  141. }
  142. /// <summary>
  143. /// Emit a KeyboardInterrupt signal to stop a running threaded virtual machine.
  144. /// </summary>
  145. public void terminate()
  146. {
  147. Bindings.pkpy_tvm_terminate(pointer);
  148. }
  149. /// <summary>
  150. /// Write a JSONRPC response to shared string buffer.
  151. /// </summary>
  152. public void write_jsonrpc_response(string value)
  153. {
  154. Bindings.pkpy_tvm_write_jsonrpc_response(pointer, value);
  155. }
  156. }
  157. }
  158. namespace pkpy
  159. {
  160. public class REPL
  161. {
  162. public IntPtr pointer { get; private set; }
  163. public VM vm { get; private set; }
  164. public REPL(VM vm)
  165. {
  166. this.vm = vm;
  167. pointer = Bindings.pkpy_new_repl(vm.pointer);
  168. }
  169. public void dispose()
  170. {
  171. Bindings.pkpy_delete(pointer);
  172. }
  173. /// <summary>
  174. /// Input a source line to an interactive console. Return `0` if need more lines, `1` if execution happened, `2` if execution skipped (compile error or empty input).
  175. /// </summary>
  176. public int input(string line)
  177. {
  178. return Bindings.pkpy_repl_input(pointer, line);
  179. }
  180. }
  181. }