p3dPythonObject.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // Filename: p3dPythonObject.cxx
  2. // Created by: drose (03Jul09)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "p3dPythonObject.h"
  15. ////////////////////////////////////////////////////////////////////
  16. // Function: P3DPythonObject::Constructor
  17. // Access: Public
  18. // Description:
  19. ////////////////////////////////////////////////////////////////////
  20. P3DPythonObject::
  21. P3DPythonObject(P3DSession *session, int object_id) :
  22. _session(session),
  23. _object_id(object_id)
  24. {
  25. _session->ref();
  26. }
  27. ////////////////////////////////////////////////////////////////////
  28. // Function: P3DPythonObject::Destructor
  29. // Access: Public, Virtual
  30. // Description:
  31. ////////////////////////////////////////////////////////////////////
  32. P3DPythonObject::
  33. ~P3DPythonObject() {
  34. // When the P3DPythonObject wrapper goes away, we have to inform the
  35. // child process that we no longer need the corresponding PyObject
  36. // to be kept around.
  37. _session->drop_pyobj(_object_id);
  38. unref_delete(_session);
  39. }
  40. ////////////////////////////////////////////////////////////////////
  41. // Function: P3DPythonObject::get_type
  42. // Access: Public, Virtual
  43. // Description: Returns the fundamental type of this kind of object.
  44. ////////////////////////////////////////////////////////////////////
  45. P3D_object_type P3DPythonObject::
  46. get_type() {
  47. return P3D_OT_object;
  48. }
  49. ////////////////////////////////////////////////////////////////////
  50. // Function: P3DPythonObject::get_bool
  51. // Access: Public, Virtual
  52. // Description: Returns the object value coerced to a boolean, if
  53. // possible.
  54. ////////////////////////////////////////////////////////////////////
  55. bool P3DPythonObject::
  56. get_bool() {
  57. bool bresult = 0;
  58. P3D_object *result = call("__bool__", NULL, 0);
  59. if (result != NULL) {
  60. bresult = P3D_OBJECT_GET_BOOL(result);
  61. P3D_OBJECT_DECREF(result);
  62. }
  63. return bresult;
  64. }
  65. ////////////////////////////////////////////////////////////////////
  66. // Function: P3DPythonObject::get_int
  67. // Access: Public, Virtual
  68. // Description: Returns the object value coerced to an integer, if
  69. // possible.
  70. ////////////////////////////////////////////////////////////////////
  71. int P3DPythonObject::
  72. get_int() {
  73. int iresult = 0;
  74. P3D_object *result = call("__int__", NULL, 0);
  75. if (result != NULL) {
  76. iresult = P3D_OBJECT_GET_INT(result);
  77. P3D_OBJECT_DECREF(result);
  78. }
  79. return iresult;
  80. }
  81. ////////////////////////////////////////////////////////////////////
  82. // Function: P3DPythonObject::get_float
  83. // Access: Public, Virtual
  84. // Description: Returns the object value coerced to a floating-point
  85. // value, if possible.
  86. ////////////////////////////////////////////////////////////////////
  87. double P3DPythonObject::
  88. get_float() {
  89. double fresult = 0.0;
  90. P3D_object *result = call("__float__", NULL, 0);
  91. if (result != NULL) {
  92. fresult = P3D_OBJECT_GET_FLOAT(result);
  93. P3D_OBJECT_DECREF(result);
  94. }
  95. return fresult;
  96. }
  97. ////////////////////////////////////////////////////////////////////
  98. // Function: P3DPythonObject::make_string
  99. // Access: Public, Virtual
  100. // Description: Fills the indicated C++ string object with the value
  101. // of this object coerced to a string.
  102. ////////////////////////////////////////////////////////////////////
  103. void P3DPythonObject::
  104. make_string(string &value) {
  105. P3D_object *result = call("__str__", NULL, 0);
  106. if (result != NULL) {
  107. int size = P3D_OBJECT_GET_STRING(result, NULL, 0);
  108. char *buffer = new char[size];
  109. P3D_OBJECT_GET_STRING(result, buffer, size);
  110. value = string(buffer, size);
  111. delete[] buffer;
  112. P3D_OBJECT_DECREF(result);
  113. }
  114. }
  115. ////////////////////////////////////////////////////////////////////
  116. // Function: P3DPythonObject::get_property
  117. // Access: Public, Virtual
  118. // Description: Returns the named property element in the object. The
  119. // return value is a new-reference P3D_object, or NULL
  120. // on error.
  121. ////////////////////////////////////////////////////////////////////
  122. P3D_object *P3DPythonObject::
  123. get_property(const string &property) {
  124. P3D_object *params[1];
  125. params[0] = new P3DStringObject(property);
  126. P3D_object *result = call("__get_property__", params, 1);
  127. P3D_OBJECT_DECREF(params[0]);
  128. return result;
  129. }
  130. ////////////////////////////////////////////////////////////////////
  131. // Function: P3DPythonObject::set_property
  132. // Access: Public, Virtual
  133. // Description: Modifies (or deletes, if value is NULL) the named
  134. // property element in the object. Returns true on
  135. // success, false on failure.
  136. ////////////////////////////////////////////////////////////////////
  137. bool P3DPythonObject::
  138. set_property(const string &property, P3D_object *value) {
  139. bool bresult = false;
  140. P3D_object *params[2];
  141. params[0] = new P3DStringObject(property);
  142. P3D_object *result = NULL;
  143. if (value == NULL) {
  144. // Delete an attribute.
  145. result = call("__del_property__", params, 1);
  146. } else {
  147. // Set a new attribute.
  148. params[1] = value;
  149. result = call("__set_property__", params, 2);
  150. }
  151. P3D_OBJECT_DECREF(params[0]);
  152. if (result != NULL) {
  153. bresult = P3D_OBJECT_GET_BOOL(result);
  154. P3D_OBJECT_DECREF(result);
  155. }
  156. return bresult;
  157. }
  158. ////////////////////////////////////////////////////////////////////
  159. // Function: P3DPythonObject::has_method
  160. // Access: Public, Virtual
  161. // Description: Returns true if the named method exists on this
  162. // object, false otherwise.
  163. ////////////////////////////////////////////////////////////////////
  164. bool P3DPythonObject::
  165. has_method(const string &method_name) {
  166. // First, check the cache.
  167. pair<HasMethod::iterator, bool> cresult = _has_method.insert(HasMethod::value_type(method_name, false));
  168. HasMethod::iterator hi = cresult.first;
  169. if (!cresult.second) {
  170. // Already cached.
  171. return (*hi).second;
  172. }
  173. bool bresult = false;
  174. P3D_object *params[1];
  175. params[0] = new P3DStringObject(method_name);
  176. P3D_object *result = call("__has_method__", params, 1);
  177. P3D_OBJECT_DECREF(params[0]);
  178. if (result != NULL) {
  179. bresult = P3D_OBJECT_GET_BOOL(result);
  180. P3D_OBJECT_DECREF(result);
  181. }
  182. // Save the cached result, so we don't have to keep asking this
  183. // question. We assume that the set of methods on an object don't
  184. // change substantially, so we can get away with keeping this cache.
  185. (*hi).second = bresult;
  186. return bresult;
  187. }
  188. ////////////////////////////////////////////////////////////////////
  189. // Function: P3DPythonObject::call
  190. // Access: Public, Virtual
  191. // Description: Invokes the named method on the object, passing the
  192. // indicated parameters. If the method name is empty,
  193. // invokes the object itself. Returns the return value
  194. // on success, NULL on error.
  195. ////////////////////////////////////////////////////////////////////
  196. P3D_object *P3DPythonObject::
  197. call(const string &method_name, P3D_object *params[], int num_params) {
  198. TiXmlDocument *doc = new TiXmlDocument;
  199. TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
  200. TiXmlElement *xcommand = new TiXmlElement("command");
  201. xcommand->SetAttribute("cmd", "pyobj");
  202. xcommand->SetAttribute("op", "call");
  203. if (!method_name.empty()) {
  204. xcommand->SetAttribute("method_name", method_name);
  205. }
  206. TiXmlElement *xobject = _session->p3dobj_to_xml(this);
  207. xobject->SetValue("object");
  208. xcommand->LinkEndChild(xobject);
  209. for (int i = 0; i < num_params; ++i) {
  210. TiXmlElement *xparams = _session->p3dobj_to_xml(params[i]);
  211. xcommand->LinkEndChild(xparams);
  212. }
  213. doc->LinkEndChild(decl);
  214. doc->LinkEndChild(xcommand);
  215. TiXmlDocument *response = _session->command_and_response(doc);
  216. P3D_object *result = NULL;
  217. if (response != NULL) {
  218. TiXmlElement *xresponse = response->FirstChildElement("response");
  219. if (xresponse != NULL) {
  220. TiXmlElement *xvalue = xresponse->FirstChildElement("value");
  221. if (xvalue != NULL) {
  222. result = _session->xml_to_p3dobj(xvalue);
  223. }
  224. }
  225. delete response;
  226. }
  227. return result;
  228. }
  229. ////////////////////////////////////////////////////////////////////
  230. // Function: P3DPythonObject::output
  231. // Access: Public, Virtual
  232. // Description: Writes a formatted representation of the value to the
  233. // indicated string. This is intended for developer
  234. // assistance.
  235. ////////////////////////////////////////////////////////////////////
  236. void P3DPythonObject::
  237. output(ostream &out) {
  238. P3D_object *result = call("__repr__", NULL, 0);
  239. out << "Python " << _object_id;
  240. if (result != NULL) {
  241. out << ": " << *result;
  242. P3D_OBJECT_DECREF(result);
  243. }
  244. }
  245. ////////////////////////////////////////////////////////////////////
  246. // Function: P3DPythonObject::fill_xml
  247. // Access: Public, Virtual
  248. // Description: If this object has a valid XML representation for the
  249. // indicated session (that hasn't already been
  250. // implemented by the generic code in P3DSession), this
  251. // method will apply it to the indicated "value" element
  252. // and return true. Otherwise, this method will leave
  253. // the element unchanged and return false.
  254. ////////////////////////////////////////////////////////////////////
  255. bool P3DPythonObject::
  256. fill_xml(TiXmlElement *xvalue, P3DSession *session) {
  257. if (session == _session) {
  258. // If it's a P3DPythonObject from the same session, just send
  259. // the object_id down, since the actual implementation of this
  260. // object exists (as a Python object) in the sub-process space.
  261. xvalue->SetAttribute("type", "python");
  262. xvalue->SetAttribute("object_id", _object_id);
  263. return true;
  264. }
  265. // Otherwise, we have to send it as a browser object.
  266. return false;
  267. }
  268. ////////////////////////////////////////////////////////////////////
  269. // Function: P3DPythonObject::get_session
  270. // Access: Public
  271. // Description: Returns the session that this object is identified
  272. // with.
  273. ////////////////////////////////////////////////////////////////////
  274. P3DSession *P3DPythonObject::
  275. get_session() {
  276. return _session;
  277. }
  278. ////////////////////////////////////////////////////////////////////
  279. // Function: P3DPythonObject::get_object_id
  280. // Access: Public
  281. // Description: Returns the object_id number that is used to uniquely
  282. // identify this object in the XML stream.
  283. ////////////////////////////////////////////////////////////////////
  284. int P3DPythonObject::
  285. get_object_id() {
  286. return _object_id;
  287. }