P3D_object needs to be reference-counted

This commit is contained in:
David Rose 2009-07-09 20:14:19 +00:00
parent e214d8c9ef
commit fbf81f90eb
31 changed files with 380 additions and 347 deletions

View File

@ -41,7 +41,7 @@ P3DBoolObject(const P3DBoolObject &copy) :
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DBoolObject::
get_type() const {
get_type() {
return P3D_OT_bool;
}
@ -52,7 +52,7 @@ get_type() const {
// possible.
////////////////////////////////////////////////////////////////////
bool P3DBoolObject::
get_bool() const {
get_bool() {
return _value;
}
@ -63,7 +63,7 @@ get_bool() const {
// possible.
////////////////////////////////////////////////////////////////////
int P3DBoolObject::
get_int() const {
get_int() {
return _value;
}
@ -74,7 +74,7 @@ get_int() const {
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DBoolObject::
make_string(string &value) const {
make_string(string &value) {
if (_value) {
value = "True";
} else {

View File

@ -28,10 +28,10 @@ public:
P3DBoolObject(const P3DBoolObject &copy);
public:
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual void make_string(string &value) const;
virtual P3D_object_type get_type();
virtual bool get_bool();
virtual int get_int();
virtual void make_string(string &value);
private:
bool _value;

View File

@ -41,7 +41,7 @@ P3DFloatObject(const P3DFloatObject &copy) :
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DFloatObject::
get_type() const {
get_type() {
return P3D_OT_float;
}
@ -52,7 +52,7 @@ get_type() const {
// possible.
////////////////////////////////////////////////////////////////////
bool P3DFloatObject::
get_bool() const {
get_bool() {
return (_value != 0.0);
}
@ -63,7 +63,7 @@ get_bool() const {
// possible.
////////////////////////////////////////////////////////////////////
int P3DFloatObject::
get_int() const {
get_int() {
return (int)_value;
}
@ -74,7 +74,7 @@ get_int() const {
// value, if possible.
////////////////////////////////////////////////////////////////////
double P3DFloatObject::
get_float() const {
get_float() {
return _value;
}
@ -85,7 +85,7 @@ get_float() const {
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DFloatObject::
make_string(string &value) const {
make_string(string &value) {
ostringstream strm;
strm << _value;
value = strm.str();

View File

@ -28,11 +28,11 @@ public:
P3DFloatObject(const P3DFloatObject &copy);
public:
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual double get_float() const;
virtual void make_string(string &value) const;
virtual P3D_object_type get_type();
virtual bool get_bool();
virtual int get_int();
virtual double get_float();
virtual void make_string(string &value);
private:
double _value;

View File

@ -73,9 +73,7 @@ P3DInstance::
~P3DInstance() {
assert(_session == NULL);
if (_browser_script_object != NULL) {
P3D_OBJECT_FINISH(_browser_script_object);
}
P3D_OBJECT_XDECREF(_browser_script_object);
DESTROY_LOCK(_request_lock);
@ -118,6 +116,7 @@ set_fparams(const P3DFileParams &fparams) {
strm << inst_mgr->get_unique_session_index();
_session_key = strm.str();
// TODO.
_python_version = "python24";
@ -200,7 +199,8 @@ get_panda_script_object() const {
}
if (result == NULL) {
result = new P3DUndefinedObject;
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
result = inst_mgr->new_undefined_object();
}
return result;
@ -211,16 +211,18 @@ get_panda_script_object() const {
// Access: Public
// Description: Stores a pointer to the top-level window object
// of the browser, to be used by Panda code to control
// JavaScript. Ownership of this object is passed into
// the instance.
// JavaScript. The new object's reference count is
// incremented, and the previous object's is
// decremented.
////////////////////////////////////////////////////////////////////
void P3DInstance::
set_browser_script_object(P3D_object *browser_script_object) {
if (browser_script_object != _browser_script_object) {
if (_browser_script_object != NULL) {
P3D_OBJECT_FINISH(_browser_script_object);
}
P3D_OBJECT_XDECREF(_browser_script_object);
_browser_script_object = browser_script_object;
if (_browser_script_object != NULL) {
P3D_OBJECT_INCREF(_browser_script_object);
}
if (_session != NULL) {
send_browser_script_object();
@ -317,6 +319,36 @@ void P3DInstance::
finish_request(P3D_request *request, bool handled) {
assert(request != NULL);
switch (request->_request_type) {
case P3D_RT_stop:
break;
case P3D_RT_get_url:
free((char *)request->_request._get_url._url);
break;
case P3D_RT_post_url:
free((char *)request->_request._post_url._url);
free((char *)request->_request._post_url._post_data);
break;
case P3D_RT_notify:
free((char *)request->_request._notify._message);
break;
case P3D_RT_script:
{
P3D_OBJECT_DECREF(request->_request._script._object);
if (request->_request._script._property_name != NULL) {
free((char *)request->_request._script._property_name);
}
for (int i = 0; i < request->_request._script._num_values; ++i) {
P3D_OBJECT_DECREF(request->_request._script._values[i]);
}
}
break;
}
delete request;
}
@ -519,7 +551,7 @@ handle_script_request(P3D_request *request) {
doc->LinkEndChild(xcommand);
if (result != NULL) {
xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
if (needs_response) {
@ -598,10 +630,6 @@ handle_script_request(P3D_request *request) {
P3D_OBJECT_CALL(object, request->_request._script._property_name,
request->_request._script._values,
request->_request._script._num_values);
// Reset the value count to 0 so we won't double-delete the
// parameter values when the request is deleted (the above call
// has already deleted them).
request->_request._script._num_values = 0;
// Feed the result back down to the subprocess.
TiXmlDocument *doc = new TiXmlDocument;
@ -615,7 +643,7 @@ handle_script_request(P3D_request *request) {
if (result != NULL) {
xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
if (needs_response) {
@ -654,7 +682,7 @@ handle_script_request(P3D_request *request) {
if (result != NULL) {
xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
logfile << "eval response: " << *doc << "\n";

View File

@ -70,3 +70,40 @@ inline int P3DInstanceManager::
get_num_instances() const {
return _instances.size();
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::new_undefined_object
// Access: Public
// Description: Returns the singleton "undefined" object, as a new
// reference.
////////////////////////////////////////////////////////////////////
inline P3D_object *P3DInstanceManager::
new_undefined_object() {
P3D_OBJECT_INCREF(_undefined_object);
return _undefined_object;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::new_none_object
// Access: Public
// Description: Returns the singleton "none" object, as a new
// reference.
////////////////////////////////////////////////////////////////////
inline P3D_object *P3DInstanceManager::
new_none_object() {
P3D_OBJECT_INCREF(_none_object);
return _none_object;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::new_bool_object
// Access: Public
// Description: Returns the singleton "true" or "false" object, as a
// new reference.
////////////////////////////////////////////////////////////////////
inline P3D_object *P3DInstanceManager::
new_bool_object(bool value) {
P3D_object *obj = (value) ? _true_object : _false_object;
P3D_OBJECT_INCREF(obj);
return obj;
}

View File

@ -18,6 +18,9 @@
#include "p3dPackage.h"
#include "p3d_plugin_config.h"
#include "p3dWinSplashWindow.h"
#include "p3dUndefinedObject.h"
#include "p3dNoneObject.h"
#include "p3dBoolObject.h"
#include "find_root_dir.h"
#include "mkdir_complete.h"
@ -43,6 +46,12 @@ P3DInstanceManager() {
_started_notify_thread = false;
INIT_THREAD(_notify_thread);
// Initialize the singleton objects.
_undefined_object = new P3DUndefinedObject();
_none_object = new P3DNoneObject();
_true_object = new P3DBoolObject(true);
_false_object = new P3DBoolObject(false);
#ifdef _WIN32
// Ensure the appropriate Windows common controls are available to
// this application.
@ -72,6 +81,22 @@ P3DInstanceManager::
assert(_instances.empty());
assert(_sessions.empty());
nout << "counts: " << _undefined_object->_ref_count
<< " " << _none_object->_ref_count
<< " " << _true_object->_ref_count
<< " " << _false_object->_ref_count
<< "\n" << flush;
assert(_undefined_object->_ref_count == 1);
assert(_none_object->_ref_count == 1);
assert(_true_object->_ref_count == 1);
assert(_false_object->_ref_count == 1);
P3D_OBJECT_DECREF(_undefined_object);
P3D_OBJECT_DECREF(_none_object);
P3D_OBJECT_DECREF(_true_object);
P3D_OBJECT_DECREF(_false_object);
#ifdef _WIN32
P3DWinSplashWindow::unregister_window_class();
#endif

View File

@ -66,6 +66,10 @@ public:
P3D_class_definition *make_class_definition() const;
inline P3D_object *new_undefined_object();
inline P3D_object *new_none_object();
inline P3D_object *new_bool_object(bool value);
static P3DInstanceManager *get_global_ptr();
static void delete_global_ptr();
@ -82,6 +86,11 @@ private:
string _download_url;
string _platform;
P3D_object *_undefined_object;
P3D_object *_none_object;
P3D_object *_true_object;
P3D_object *_false_object;
typedef set<P3DInstance *> Instances;
Instances _instances;

View File

@ -41,7 +41,7 @@ P3DIntObject(const P3DIntObject &copy) :
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DIntObject::
get_type() const {
get_type() {
return P3D_OT_int;
}
@ -52,7 +52,7 @@ get_type() const {
// possible.
////////////////////////////////////////////////////////////////////
bool P3DIntObject::
get_bool() const {
get_bool() {
return (_value != 0);
}
@ -63,7 +63,7 @@ get_bool() const {
// possible.
////////////////////////////////////////////////////////////////////
int P3DIntObject::
get_int() const {
get_int() {
return _value;
}
@ -74,7 +74,7 @@ get_int() const {
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DIntObject::
make_string(string &value) const {
make_string(string &value) {
ostringstream strm;
strm << _value;
value = strm.str();

View File

@ -28,10 +28,10 @@ public:
P3DIntObject(const P3DIntObject &copy);
public:
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual void make_string(string &value) const;
virtual P3D_object_type get_type();
virtual bool get_bool();
virtual int get_int();
virtual void make_string(string &value);
private:
int _value;

View File

@ -29,7 +29,7 @@ P3DNoneObject() {
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DNoneObject::
get_type() const {
get_type() {
return P3D_OT_none;
}
@ -40,7 +40,7 @@ get_type() const {
// possible.
////////////////////////////////////////////////////////////////////
bool P3DNoneObject::
get_bool() const {
get_bool() {
return false;
}
@ -51,6 +51,6 @@ get_bool() const {
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DNoneObject::
make_string(string &value) const {
make_string(string &value) {
value = "None";
}

View File

@ -28,9 +28,9 @@ public:
P3DNoneObject();
public:
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual void make_string(string &value) const;
virtual P3D_object_type get_type();
virtual bool get_bool();
virtual void make_string(string &value);
};
#endif

View File

@ -37,39 +37,3 @@ P3DObject(const P3DObject &copy) {
_class = copy._class;
_ref_count = 1;
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::ref
// Access: Public
// Description: Increments the reference count.
////////////////////////////////////////////////////////////////////
inline void P3DObject::
ref() const {
++(((P3DObject *)this)->_ref_count);
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::unref
// Access: Public
// Description: Decrements the reference count, and returns the new
// count.
////////////////////////////////////////////////////////////////////
inline int P3DObject::
unref() const {
--(((P3DObject *)this)->_ref_count);
return _ref_count;
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::unref_delete
// Access: Public, Static
// Description: Decrements the reference count on the indicated
// object, and deletes it if the reference count reaches
// zero.
////////////////////////////////////////////////////////////////////
inline void P3DObject::
unref_delete(P3DObject *obj) {
if (obj->unref() <= 0) {
delete obj;
}
}

View File

@ -21,47 +21,42 @@
// P3D_object structure.
static void
object_finish(P3D_object *object) {
P3DObject::unref_delete(((P3DObject *)object));
}
static P3D_object *
object_copy(const P3D_object *object) {
return ((const P3DObject *)object)->make_copy();
delete (P3DObject *)object;
}
static P3D_object_type
object_get_type(const P3D_object *object) {
return ((const P3DObject *)object)->get_type();
object_get_type(P3D_object *object) {
return ((P3DObject *)object)->get_type();
}
static bool
object_get_bool(const P3D_object *object) {
return ((const P3DObject *)object)->get_bool();
object_get_bool(P3D_object *object) {
return ((P3DObject *)object)->get_bool();
}
static int
object_get_int(const P3D_object *object) {
return ((const P3DObject *)object)->get_int();
object_get_int(P3D_object *object) {
return ((P3DObject *)object)->get_int();
}
static double
object_get_float(const P3D_object *object) {
return ((const P3DObject *)object)->get_float();
object_get_float(P3D_object *object) {
return ((P3DObject *)object)->get_float();
}
static int
object_get_string(const P3D_object *object, char *buffer, int buffer_length) {
return ((const P3DObject *)object)->get_string(buffer, buffer_length);
object_get_string(P3D_object *object, char *buffer, int buffer_length) {
return ((P3DObject *)object)->get_string(buffer, buffer_length);
}
static int
object_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
return ((const P3DObject *)object)->get_repr(buffer, buffer_length);
object_get_repr(P3D_object *object, char *buffer, int buffer_length) {
return ((P3DObject *)object)->get_repr(buffer, buffer_length);
}
static P3D_object *
object_get_property(const P3D_object *object, const char *property) {
return ((const P3DObject *)object)->get_property(property);
object_get_property(P3D_object *object, const char *property) {
return ((P3DObject *)object)->get_property(property);
}
static bool
@ -71,27 +66,26 @@ object_set_property(P3D_object *object, const char *property,
}
static bool
object_has_method(const P3D_object *object, const char *method_name) {
return ((const P3DObject *)object)->has_method(method_name);
object_has_method(P3D_object *object, const char *method_name) {
return ((P3DObject *)object)->has_method(method_name);
}
static P3D_object *
object_call(const P3D_object *object, const char *method_name,
object_call(P3D_object *object, const char *method_name,
P3D_object *params[], int num_params) {
if (method_name == NULL) {
method_name = "";
}
return ((const P3DObject *)object)->call(method_name, params, num_params);
return ((P3DObject *)object)->call(method_name, params, num_params);
}
static P3D_object *
object_eval(const P3D_object *object, const char *expression) {
return ((const P3DObject *)object)->eval(expression);
object_eval(P3D_object *object, const char *expression) {
return ((P3DObject *)object)->eval(expression);
}
P3D_class_definition P3DObject::_object_class = {
&object_finish,
&object_copy,
&object_get_type,
&object_get_bool,
&object_get_int,
@ -116,14 +110,8 @@ generic_finish(P3D_object *object) {
nout << "Warning! default object_finish() method does nothing; object will leak.\n" << flush;
}
static P3D_object *
generic_copy(const P3D_object *object) {
nout << "Warning! default object_copy() method does nothing; object pointer will be shared.\n" << flush;
return (P3D_object *)object;
}
static P3D_object_type
generic_get_type(const P3D_object *object) {
generic_get_type(P3D_object *object) {
// We assume anyone going through the trouble of subclassing this
// will want to return an object, not one of the other fundamental
// types.
@ -131,66 +119,59 @@ generic_get_type(const P3D_object *object) {
}
static bool
generic_get_bool(const P3D_object *object) {
generic_get_bool(P3D_object *object) {
return false;
}
static int
generic_get_int(const P3D_object *object) {
generic_get_int(P3D_object *object) {
return 0;
}
static double
generic_get_float(const P3D_object *object) {
generic_get_float(P3D_object *object) {
return 0.0;
}
static int
generic_get_string(const P3D_object *object, char *buffer, int buffer_length) {
generic_get_string(P3D_object *object, char *buffer, int buffer_length) {
return 0;
}
static int
generic_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
generic_get_repr(P3D_object *object, char *buffer, int buffer_length) {
return 0;
}
static P3D_object *
generic_get_property(const P3D_object *object, const char *property) {
generic_get_property(P3D_object *object, const char *property) {
return NULL;
}
static bool
generic_set_property(P3D_object *object, const char *property,
P3D_object *value) {
if (value != NULL) {
P3D_OBJECT_FINISH(value);
}
return false;
}
static bool
generic_has_method(const P3D_object *object, const char *method_name) {
return ((const P3DObject *)object)->has_method(method_name);
generic_has_method(P3D_object *object, const char *method_name) {
return false;
}
static P3D_object *
generic_call(const P3D_object *object, const char *method_name,
generic_call(P3D_object *object, const char *method_name,
P3D_object *params[], int num_params) {
for (int i = 0; i < num_params; ++i) {
P3D_OBJECT_FINISH(params[i]);
}
return NULL;
}
static P3D_object *
generic_eval(const P3D_object *object, const char *expression) {
generic_eval(P3D_object *object, const char *expression) {
return NULL;
}
P3D_class_definition P3DObject::_generic_class = {
&generic_finish,
&generic_copy,
&generic_get_type,
&generic_get_bool,
&generic_get_int,
@ -211,20 +192,7 @@ P3D_class_definition P3DObject::_generic_class = {
////////////////////////////////////////////////////////////////////
P3DObject::
~P3DObject() {
}
////////////////////////////////////////////////////////////////////
// Function: P3DObject::make_copy
// Access: Public, Virtual
// Description: Returns a new copy of the object, if necessary. If
// the object type is static and all instances are
// identical, this actually simply ups the reference
// count and returns the same object.
////////////////////////////////////////////////////////////////////
P3DObject *P3DObject::
make_copy() const {
ref();
return (P3DObject *)this;
assert(_ref_count == 0);
}
////////////////////////////////////////////////////////////////////
@ -234,7 +202,7 @@ make_copy() const {
// possible.
////////////////////////////////////////////////////////////////////
int P3DObject::
get_int() const {
get_int() {
return 0;
}
@ -245,7 +213,7 @@ get_int() const {
// value, if possible.
////////////////////////////////////////////////////////////////////
double P3DObject::
get_float() const {
get_float() {
return get_int();
}
@ -260,7 +228,7 @@ get_float() const {
// was too small).
////////////////////////////////////////////////////////////////////
int P3DObject::
get_string(char *buffer, int buffer_length) const {
get_string(char *buffer, int buffer_length) {
string result;
make_string(result);
strncpy(buffer, result.c_str(), buffer_length);
@ -274,7 +242,7 @@ get_string(char *buffer, int buffer_length) const {
// similar to get_string(), above.
////////////////////////////////////////////////////////////////////
int P3DObject::
get_repr(char *buffer, int buffer_length) const {
get_repr(char *buffer, int buffer_length) {
ostringstream strm;
output(strm);
string result = strm.str();
@ -290,7 +258,7 @@ get_repr(char *buffer, int buffer_length) const {
// that must be deleted by the caller, or NULL on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DObject::
get_property(const string &property) const {
get_property(const string &property) {
return NULL;
}
@ -303,9 +271,6 @@ get_property(const string &property) const {
////////////////////////////////////////////////////////////////////
bool P3DObject::
set_property(const string &property, P3D_object *value) {
if (value != NULL) {
P3D_OBJECT_FINISH(value);
}
return false;
}
@ -316,7 +281,7 @@ set_property(const string &property, P3D_object *value) {
// object, false otherwise.
////////////////////////////////////////////////////////////////////
bool P3DObject::
has_method(const string &method_name) const {
has_method(const string &method_name) {
return false;
}
@ -329,10 +294,7 @@ has_method(const string &method_name) const {
// on success, NULL on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DObject::
call(const string &method_name, P3D_object *params[], int num_params) const {
for (int i = 0; i < num_params; ++i) {
P3D_OBJECT_FINISH(params[i]);
}
call(const string &method_name, P3D_object *params[], int num_params) {
return NULL;
}
@ -343,7 +305,7 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
// of the P3DObject classes implement this.
////////////////////////////////////////////////////////////////////
P3D_object *P3DObject::
eval(const string &expression) const {
eval(const string &expression) {
return NULL;
}
@ -355,7 +317,7 @@ eval(const string &expression) const {
// assistance.
////////////////////////////////////////////////////////////////////
void P3DObject::
output(ostream &out) const {
output(ostream &out) {
string value;
make_string(value);
out << value;

View File

@ -33,32 +33,24 @@ protected:
public:
virtual ~P3DObject();
virtual P3DObject *make_copy() const;
virtual P3D_object_type get_type() const=0;
virtual bool get_bool() const=0;
virtual int get_int() const;
virtual double get_float() const;
virtual P3D_object_type get_type()=0;
virtual bool get_bool()=0;
virtual int get_int();
virtual double get_float();
int get_string(char *buffer, int buffer_length) const;
int get_repr(char *buffer, int buffer_length) const;
virtual void make_string(string &value) const=0;
int get_string(char *buffer, int buffer_length);
int get_repr(char *buffer, int buffer_length);
virtual void make_string(string &value)=0;
virtual P3D_object *get_property(const string &property) const;
virtual P3D_object *get_property(const string &property);
virtual bool set_property(const string &property, P3D_object *value);
virtual bool has_method(const string &method_name) const;
virtual bool has_method(const string &method_name);
virtual P3D_object *call(const string &method_name,
P3D_object *params[], int num_params) const;
virtual P3D_object *eval(const string &expression) const;
P3D_object *params[], int num_params);
virtual P3D_object *eval(const string &expression);
virtual void output(ostream &out) const;
inline void ref() const;
inline int unref() const;
static inline void unref_delete(P3DObject *obj);
private:
int _ref_count;
virtual void output(ostream &out);
public:
static P3D_class_definition _object_class;
@ -71,7 +63,7 @@ public:
// virtual method to write the output simply. (For classes that
// inherit only from P3D_object, we have to use the generic C method
// defined in p3d_plugin_common.h, a little clumsier.)
inline ostream &operator << (ostream &out, const P3DObject &value) {
inline ostream &operator << (ostream &out, P3DObject &value) {
value.output(out);
return out;
}

View File

@ -42,7 +42,7 @@ P3DPythonObject::
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DPythonObject::
get_type() const {
get_type() {
return P3D_OT_object;
}
@ -53,13 +53,13 @@ get_type() const {
// possible.
////////////////////////////////////////////////////////////////////
bool P3DPythonObject::
get_bool() const {
get_bool() {
bool bresult = 0;
P3D_object *result = call("__bool__", NULL, 0);
if (result != NULL) {
bresult = P3D_OBJECT_GET_BOOL(result);
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
return bresult;
@ -72,13 +72,13 @@ get_bool() const {
// possible.
////////////////////////////////////////////////////////////////////
int P3DPythonObject::
get_int() const {
get_int() {
int iresult = 0;
P3D_object *result = call("__int__", NULL, 0);
if (result != NULL) {
iresult = P3D_OBJECT_GET_INT(result);
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
return iresult;
@ -91,13 +91,13 @@ get_int() const {
// value, if possible.
////////////////////////////////////////////////////////////////////
double P3DPythonObject::
get_float() const {
get_float() {
double fresult = 0.0;
P3D_object *result = call("__float__", NULL, 0);
if (result != NULL) {
fresult = P3D_OBJECT_GET_FLOAT(result);
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
return fresult;
@ -110,7 +110,7 @@ get_float() const {
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DPythonObject::
make_string(string &value) const {
make_string(string &value) {
P3D_object *result = call("__str__", NULL, 0);
if (result != NULL) {
int size = P3D_OBJECT_GET_STRING(result, NULL, 0);
@ -119,7 +119,7 @@ make_string(string &value) const {
value = string(buffer, size);
delete[] buffer;
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
}
@ -131,7 +131,7 @@ make_string(string &value) const {
// that must be deleted by the caller, or NULL on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DPythonObject::
get_property(const string &property) const {
get_property(const string &property) {
P3D_object *params[1];
params[0] = new P3DStringObject(property);
@ -167,7 +167,7 @@ set_property(const string &property, P3D_object *value) {
if (result != NULL) {
bresult = P3D_OBJECT_GET_BOOL(result);
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
return bresult;
@ -180,7 +180,7 @@ set_property(const string &property, P3D_object *value) {
// object, false otherwise.
////////////////////////////////////////////////////////////////////
bool P3DPythonObject::
has_method(const string &method_name) const {
has_method(const string &method_name) {
bool bresult = false;
P3D_object *params[1];
@ -190,7 +190,7 @@ has_method(const string &method_name) const {
if (result != NULL) {
bresult = P3D_OBJECT_GET_BOOL(result);
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
return bresult;
@ -205,7 +205,7 @@ has_method(const string &method_name) const {
// on success, NULL on error.
////////////////////////////////////////////////////////////////////
P3D_object *P3DPythonObject::
call(const string &method_name, P3D_object *params[], int num_params) const {
call(const string &method_name, P3D_object *params[], int num_params) {
TiXmlDocument *doc = new TiXmlDocument;
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
TiXmlElement *xcommand = new TiXmlElement("command");
@ -222,10 +222,6 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
for (int i = 0; i < num_params; ++i) {
TiXmlElement *xparams = _session->p3dobj_to_xml(params[i]);
xcommand->LinkEndChild(xparams);
// Now we're done with the params object passed in, we can delete
// it as promised.
P3D_OBJECT_FINISH(params[i]);
}
doc->LinkEndChild(decl);
@ -255,12 +251,12 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
// assistance.
////////////////////////////////////////////////////////////////////
void P3DPythonObject::
output(ostream &out) const {
output(ostream &out) {
P3D_object *result = call("__repr__", NULL, 0);
out << "Python " << _object_id;
if (result != NULL) {
out << ": " << *result;
P3D_OBJECT_FINISH(result);
P3D_OBJECT_DECREF(result);
}
}
@ -271,7 +267,7 @@ output(ostream &out) const {
// identify this object in the XML stream.
////////////////////////////////////////////////////////////////////
int P3DPythonObject::
get_object_id() const {
get_object_id() {
return _object_id;
}

View File

@ -34,22 +34,22 @@ public:
virtual ~P3DPythonObject();
public:
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual int get_int() const;
virtual double get_float() const;
virtual P3D_object_type get_type();
virtual bool get_bool();
virtual int get_int();
virtual double get_float();
virtual void make_string(string &value) const;
virtual void make_string(string &value);
virtual P3D_object *get_property(const string &property) const;
virtual P3D_object *get_property(const string &property);
virtual bool set_property(const string &property, P3D_object *value);
virtual bool has_method(const string &method_name) const;
virtual bool has_method(const string &method_name);
virtual P3D_object *call(const string &method_name,
P3D_object *params[], int num_params) const;
P3D_object *params[], int num_params);
virtual void output(ostream &out) const;
int get_object_id() const;
virtual void output(ostream &out);
int get_object_id();
private:
P3DSession *_session;

View File

@ -321,21 +321,23 @@ command_and_response(TiXmlDocument *command) {
// Access: Public
// Description: Converts the XML representation of the particular
// object value into a corresponding P3D_object.
// Returns the newly-allocated object.
// Returns the object, a new reference.
////////////////////////////////////////////////////////////////////
P3D_object *P3DSession::
xml_to_p3dobj(const TiXmlElement *xvalue) {
const char *type = xvalue->Attribute("type");
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
if (strcmp(type, "undefined") == 0) {
return new P3DUndefinedObject;
return inst_mgr->new_undefined_object();
} else if (strcmp(type, "none") == 0) {
return new P3DNoneObject;
return inst_mgr->new_none_object();
} else if (strcmp(type, "bool") == 0) {
int value;
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
return new P3DBoolObject(value != 0);
return inst_mgr->new_bool_object(value != 0);
}
} else if (strcmp(type, "int") == 0) {
@ -364,11 +366,12 @@ xml_to_p3dobj(const TiXmlElement *xvalue) {
SentObjects::iterator si = _sent_objects.find(object_id);
if (si == _sent_objects.end()) {
// Hmm, the child process gave us a bogus object ID.
return new P3DUndefinedObject;
return inst_mgr->new_undefined_object();
}
P3D_object *obj = (*si).second;
return P3D_OBJECT_COPY(obj);
P3D_OBJECT_INCREF(obj);
return obj;
}
} else if (strcmp(type, "python") == 0) {
@ -379,7 +382,7 @@ xml_to_p3dobj(const TiXmlElement *xvalue) {
}
// Something went wrong in decoding.
return new P3DUndefinedObject;
return inst_mgr->new_undefined_object();
}
////////////////////////////////////////////////////////////////////
@ -387,10 +390,11 @@ xml_to_p3dobj(const TiXmlElement *xvalue) {
// Access: Public
// Description: Allocates and returns a new XML structure
// corresponding to the indicated value. The supplied
// P3DObject passed in is *not* deleted.
// P3DObject's reference count is not decremented; the
// caller remains responsible for decrementing it later.
////////////////////////////////////////////////////////////////////
TiXmlElement *P3DSession::
p3dobj_to_xml(const P3D_object *obj) {
p3dobj_to_xml(P3D_object *obj) {
TiXmlElement *xvalue = new TiXmlElement("value");
switch (P3D_OBJECT_GET_TYPE(obj)) {
@ -443,21 +447,21 @@ p3dobj_to_xml(const P3D_object *obj) {
// should pass a reference down to this particular object, so
// the Python process knows to call back up to here to query it.
P3D_object *dup = P3D_OBJECT_COPY(obj);
int object_id = _next_sent_id;
++_next_sent_id;
bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, dup)).second;
bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
while (!inserted) {
// Hmm, we must have cycled around the entire int space? Either
// that, or there's a logic bug somewhere. Assume the former,
// and keep looking for an empty slot.
object_id = _next_sent_id;
++_next_sent_id;
inserted = _sent_objects.insert(SentObjects::value_type(object_id, dup)).second;
inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
}
// Now that it's stored in the map, increment its reference count.
// TODO: implement removing things from this map.
P3D_OBJECT_INCREF(obj);
xvalue->SetAttribute("type", "browser");
xvalue->SetAttribute("object_id", object_id);

View File

@ -50,7 +50,7 @@ public:
void send_command(TiXmlDocument *command);
TiXmlDocument *command_and_response(TiXmlDocument *command);
P3D_object *xml_to_p3dobj(const TiXmlElement *xvalue);
TiXmlElement *p3dobj_to_xml(const P3D_object *obj);
TiXmlElement *p3dobj_to_xml(P3D_object *obj);
private:
void install_progress(P3DPackage *package, double progress);

View File

@ -50,7 +50,7 @@ P3DStringObject::
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DStringObject::
get_type() const {
get_type() {
return P3D_OT_string;
}
@ -61,7 +61,7 @@ get_type() const {
// possible.
////////////////////////////////////////////////////////////////////
bool P3DStringObject::
get_bool() const {
get_bool() {
return !_value.empty();
}
@ -72,7 +72,7 @@ get_bool() const {
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DStringObject::
make_string(string &value) const {
make_string(string &value) {
value = _value;
}
@ -84,7 +84,7 @@ make_string(string &value) const {
// assistance.
////////////////////////////////////////////////////////////////////
void P3DStringObject::
output(ostream &out) const {
output(ostream &out) {
out << '"';
for (string::const_iterator si = _value.begin(); si != _value.end(); ++si) {
if (isprint(*si)) {

View File

@ -30,11 +30,11 @@ public:
public:
virtual ~P3DStringObject();
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual void make_string(string &value) const;
virtual P3D_object_type get_type();
virtual bool get_bool();
virtual void make_string(string &value);
virtual void output(ostream &out) const;
virtual void output(ostream &out);
private:
string _value;

View File

@ -29,7 +29,7 @@ P3DUndefinedObject() {
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DUndefinedObject::
get_type() const {
get_type() {
return P3D_OT_undefined;
}
@ -40,7 +40,7 @@ get_type() const {
// possible.
////////////////////////////////////////////////////////////////////
bool P3DUndefinedObject::
get_bool() const {
get_bool() {
return false;
}
@ -51,6 +51,6 @@ get_bool() const {
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DUndefinedObject::
make_string(string &value) const {
make_string(string &value) {
value = "Undefined";
}

View File

@ -29,9 +29,9 @@ public:
P3DUndefinedObject();
public:
virtual P3D_object_type get_type() const;
virtual bool get_bool() const;
virtual void make_string(string &value) const;
virtual P3D_object_type get_type();
virtual bool get_bool();
virtual void make_string(string &value);
};
#endif

View File

@ -138,7 +138,8 @@ P3D_new_undefined_object() {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3D_object *result = new P3DUndefinedObject();
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
P3D_object *result = inst_mgr->new_undefined_object();
RELEASE_LOCK(_api_lock);
return result;
@ -149,7 +150,8 @@ P3D_new_none_object() {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3D_object *result = new P3DNoneObject();
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
P3D_object *result = inst_mgr->new_none_object();
RELEASE_LOCK(_api_lock);
return result;
@ -160,7 +162,8 @@ P3D_new_bool_object(bool value) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3D_object *result = new P3DBoolObject(value);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
P3D_object *result = inst_mgr->new_bool_object(value);
RELEASE_LOCK(_api_lock);
return result;
@ -212,7 +215,7 @@ P3D_instance_get_panda_script_object(P3D_instance *instance) {
void
P3D_instance_set_browser_script_object(P3D_instance *instance,
P3D_object *object) {
P3D_object *object) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);

View File

@ -307,25 +307,30 @@ typedef enum {
P3D_OT_object,
} P3D_object_type;
/* Most methods and functions that return a P3D_object return it with
its reference count already incremented by one for the benefit of
the caller, leaving the caller the owner of the implicit reference
count. This is referred to as returning a "new reference", using
the Python naming convention. Similarly, most methods that receive
a P3D_object will implicitly increment the reference count
internally if necessary, leaving the caller still the owner of its
own reference count. Thus, it is the caller's responsibility to
call P3D_OBJECT_DECREF() on any P3D_objects it has received but no
longer wishes to keep. */
/* This method is called to deallocate the object and all of its
internal structures. */
internal structures. Do not call it directly; call
P3D_OBJECT_DECREF() instead. */
typedef void
P3D_object_finish_method(P3D_object *object);
/* Returns a new copy of the object. The caller receives ownership of
the new object and must eventually pass its pointer to
P3D_OBJECT_FINISH() to delete it, or into some other call that
transfers ownership. */
typedef P3D_object *
P3D_object_copy_method(const P3D_object *object);
/* Returns the fundamental type of the object. This should be treated
as a hint to suggest how the object can most accurately be
represented; it does not limit the actual interfaces available to
an object. For instance, you may call P3D_OBJECT_GET_PROPERTY()
even if the object's type is not "object". */
typedef P3D_object_type
P3D_object_get_type_method(const P3D_object *object);
P3D_object_get_type_method(P3D_object *object);
/* Each of the following methods returns the object's value expressed
as the corresponding type. If the object is not precisely that
@ -333,15 +338,15 @@ P3D_object_get_type_method(const P3D_object *object);
/* Return the object as a bool. */
typedef bool
P3D_object_get_bool_method(const P3D_object *object);
P3D_object_get_bool_method(P3D_object *object);
/* Return the object as an integer. */
typedef int
P3D_object_get_int_method(const P3D_object *object);
P3D_object_get_int_method(P3D_object *object);
/* Return the object as a floating-point number. */
typedef double
P3D_object_get_float_method(const P3D_object *object);
P3D_object_get_float_method(P3D_object *object);
/* Get the object as a string. This method copies the string into the
provided buffer, and returns the actual length of the internal
@ -352,7 +357,7 @@ P3D_object_get_float_method(const P3D_object *object);
buffer = NULL and buffer_length = 0 to return just the required
size of the buffer. */
typedef int
P3D_object_get_string_method(const P3D_object *object,
P3D_object_get_string_method(P3D_object *object,
char *buffer, int buffer_length);
/* As above, but instead of the literal object data, returns a
@ -362,23 +367,19 @@ P3D_object_get_string_method(const P3D_object *object,
marks and escape characters from P3D_OBJECT_GET_REPR().
Mechanically, this function works the same way as get_string(). */
typedef int
P3D_object_get_repr_method(const P3D_object *object,
P3D_object_get_repr_method(P3D_object *object,
char *buffer, int buffer_length);
/* Looks up a property on the object by name, i.e. a data member or a
method. The return value is a newly-allocated P3D_object if the
property exists, or NULL if it does not. If it is not NULL,
ownership of the return value is transferred to the caller, who
will be responsible for deleting it later. */
method. The return value is a new-reference P3D_object if the
property exists, or NULL if it does not. */
typedef P3D_object *
P3D_object_get_property_method(const P3D_object *object, const char *property);
P3D_object_get_property_method(P3D_object *object, const char *property);
/* Changes the value at the indicated property. Any existing object
already at the corresponding property is deleted. If the value
object pointer is NULL, the property is deleted. Returns true on
success, false on failure. The caller must have ownership of the
value object before the call; after the call, ownership of the
value object is transferred to this object. */
pointer is NULL, the property is deleted. Returns true on success,
false on failure. */
typedef bool
P3D_object_set_property_method(P3D_object *object, const char *property,
P3D_object *value);
@ -389,36 +390,32 @@ P3D_object_set_property_method(P3D_object *object, const char *property,
a callable object. If method_name is empty or NULL, returns true
if the object itself is callable. */
typedef bool
P3D_object_has_method_method(const P3D_object *object, const char *method_name);
P3D_object_has_method_method(P3D_object *object, const char *method_name);
/* Invokes a named method on the object. If method_name is empty or
NULL, invokes the object itself as a function. You must pass an
array of P3D_objects as the list of parameters. The ownership of
each of the parameters in this array (but not of the array pointer
itself) is passed into this call; the objects will be deleted when
the call is completed.
array of P3D_objects as the list of parameters, and ownership of
these objects' reference counts is not transferred with the call
(you must still DECREF these objects afterwards).
The return value is a newly-allocated P3D_object on success, or
NULL on failure. Ownership of the return value is transferred to
the caller. */
The return value is a new-reference P3D_object on success, or NULL
on failure. */
typedef P3D_object *
P3D_object_call_method(const P3D_object *object, const char *method_name,
P3D_object_call_method(P3D_object *object, const char *method_name,
P3D_object *params[], int num_params);
/* Evaluates an arbitrary JavaScript expression in the context of the
object.
The return value is a newly-allocated P3D_object on success, or
NULL on failure. Ownership of the return value is transferred to
the caller. */
The return value is a new-reference P3D_object on success, or NULL
on failure. */
typedef P3D_object *
P3D_object_eval_method(const P3D_object *object, const char *expression);
P3D_object_eval_method(P3D_object *object, const char *expression);
/* This defines the class structure that implements all of the above
methods. */
typedef struct _P3D_class_definition {
P3D_object_finish_method *_finish;
P3D_object_copy_method *_copy;
P3D_object_get_type_method *_get_type;
P3D_object_get_bool_method *_get_bool;
@ -439,6 +436,7 @@ typedef struct _P3D_class_definition {
/* And this structure defines the actual instances of P3D_object. */
struct _P3D_object {
const P3D_class_definition *_class;
int _ref_count;
/* Additional opaque data may be stored here. */
};
@ -446,9 +444,6 @@ struct _P3D_object {
/* These macros are defined for the convenience of invoking any of the
above method functions on an object. */
#define P3D_OBJECT_FINISH(object) ((object)->_class->_finish((object)))
#define P3D_OBJECT_COPY(object) ((object)->_class->_copy((object)))
#define P3D_OBJECT_GET_TYPE(object) ((object)->_class->_get_type((object)))
#define P3D_OBJECT_GET_BOOL(object) ((object)->_class->_get_bool((object)))
#define P3D_OBJECT_GET_INT(object) ((object)->_class->_get_int((object)))
@ -463,58 +458,65 @@ struct _P3D_object {
#define P3D_OBJECT_CALL(object, method_name, params, num_params) ((object)->_class->_call((object), (method_name), (params), (num_params)))
#define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression)))
/* These macros are provided to manipulate the reference count of the
indicated object. Following Python's convention, XDECREF is
provided to decrement the reference count for a pointer that might
be NULL (it does nothing in the case of a NULL pointer). */
/* The following function types are once again meant to define
actual function pointers to be found within the core API DLL. */
#define P3D_OBJECT_INCREF(object) (++(object)->_ref_count)
#define P3D_OBJECT_DECREF(object) { if (--(object)->_ref_count <= 0) { (object)->_class->_finish((object)); } }
#define P3D_OBJECT_XDECREF(object) { if ((object) != (P3D_object *)NULL) { P3D_OBJECT_DECREF(object); } }
/* Returns a newly-allocated P3D_class_definition object, filled with
generic function pointers that have reasonable default behavior for
all methods. The host should use this function to get a clean
/* End of method pointer definitions. The following function types
are once again meant to define actual function pointers to be found
within the core API DLL. */
/* Returns a new P3D_class_definition object, filled with generic
function pointers that have reasonable default behavior for all
methods. The host should use this function to get a clean
P3D_class_definition object before calling
P3D_instance_set_browser_script_object() (see below). Note that this
pointer will automatically be freed when P3D_finalize() is
P3D_instance_set_browser_script_object() (see below). Note that
this pointer will automatically be freed when P3D_finalize() is
called. */
typedef P3D_class_definition *
P3D_make_class_definition_func();
/* Allocates a new P3D_object of type "undefined". This corresponds
to the undefined or void type on JavaScript. It is similar to
Python's None, but has a subtly different shade of meaning; we map
it to an explicit Undefined instance in runp3d.py. */
/* Returns a new-reference P3D_object of type "undefined". This
corresponds to the undefined or void type on JavaScript. It is
similar to Python's None, but has a subtly different shade of
meaning; we map it to an explicit Undefined instance in
runp3d.py. */
typedef P3D_object *
P3D_new_undefined_object_func();
/* Allocates a new P3D_object of type none. This value has no
/* Returns a new-reference P3D_object of type none. This value has no
particular value and corresponds to Python's None type or
JavaScript's null type. */
typedef P3D_object *
P3D_new_none_object_func();
/* Allocates a new P3D_object of type bool. */
/* Returns a new-reference P3D_object of type bool. */
typedef P3D_object *
P3D_new_bool_object_func(bool value);
/* Allocates a new P3D_object of type int. */
/* Returns a new-reference P3D_object of type int. */
typedef P3D_object *
P3D_new_int_object_func(int value);
/* Allocates a new P3D_object of type float. */
/* Returns a new-reference P3D_object of type float. */
typedef P3D_object *
P3D_new_float_object_func(double value);
/* Allocates a new P3D_object of type string. The supplied string is
copied into the object and stored internally. */
/* Returns a new-reference P3D_object of type string. The supplied
string is copied into the object and stored internally. */
typedef P3D_object *
P3D_new_string_object_func(const char *string, int length);
/* Returns a pointer to the top-level scriptable object of the
instance. Scripts running on the host may use this object to
communicate with the instance, by using the above methods to set or
query properties, and/or call methods, on the instance.
The return value from this function is a newly-allocated object;
ownership of the object is passed to the caller, who should be
responsible for deleting it eventually. */
/* Returns a new-reference pointer to the top-level scriptable object
of the instance. Scripts running on the host may use this object
to communicate with the instance, by using the above methods to set
or query properties, and/or call methods, on the instance. */
typedef P3D_object *
P3D_instance_get_panda_script_object_func(P3D_instance *instance);
@ -528,8 +530,8 @@ P3D_instance_get_panda_script_object_func(P3D_instance *instance);
have a custom P3D_class_definition pointer, which also must have
been created by the host. The best way to create an appropriate
class definition is call P3D_make_class_definition(), and then
replace the function pointers for at least _finish, _copy,
_get_property, _set_property, and _call. Set these pointers to the
replace the function pointers for at least _finish, _get_property,
_set_property, _has_method, and _call. Set these pointers to the
host's own functions that make the appropriate changes in the DOM,
or invoke the appropriate JavaScript functions.
@ -538,10 +540,10 @@ P3D_instance_get_panda_script_object_func(P3D_instance *instance);
able to control the instance via P3D_instance_get_panda_script_object(),
above.
Ownership of the object is passed into the instance. The caller
must have freshly allocated the object, and should no longer store
or delete it. The instance will eventually delete it by calling
its _finish method. */
Note that the object's constructor should initialize its reference
count to 1. The instance will increment reference count as a
result of this call; the caller is responsible for calling DECREF
on the object after this call to remove its own reference. */
typedef void
P3D_instance_set_browser_script_object_func(P3D_instance *instance,
P3D_object *object);

View File

@ -41,7 +41,7 @@ extern ostream *nout_stream;
// A convenience function for formatting a generic P3D_object to an
// ostream.
inline ostream &
operator << (ostream &out, const P3D_object &value) {
operator << (ostream &out, P3D_object &value) {
int size = P3D_OBJECT_GET_REPR(&value, NULL, 0);
char *buffer = new char[size];
P3D_OBJECT_GET_REPR(&value, buffer, size);

View File

@ -26,18 +26,13 @@ object_finish(P3D_object *object) {
delete ((PPBrowserObject *)object);
}
static P3D_object *
object_copy(const P3D_object *object) {
return new PPBrowserObject(*(const PPBrowserObject *)object);
}
static int
object_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
object_get_repr(P3D_object *object, char *buffer, int buffer_length) {
return ((const PPBrowserObject *)object)->get_repr(buffer, buffer_length);
}
static P3D_object *
object_get_property(const P3D_object *object, const char *property) {
object_get_property(P3D_object *object, const char *property) {
return ((const PPBrowserObject *)object)->get_property(property);
}
@ -48,7 +43,7 @@ object_set_property(P3D_object *object, const char *property,
}
static P3D_object *
object_call(const P3D_object *object, const char *method_name,
object_call(P3D_object *object, const char *method_name,
P3D_object *params[], int num_params) {
if (method_name == NULL) {
method_name = "";
@ -57,7 +52,7 @@ object_call(const P3D_object *object, const char *method_name,
}
static P3D_object *
object_eval(const P3D_object *object, const char *expression) {
object_eval(P3D_object *object, const char *expression) {
return ((const PPBrowserObject *)object)->eval(expression);
}
@ -74,6 +69,7 @@ PPBrowserObject(PPInstance *inst, NPObject *npobj) :
_npobj(npobj)
{
_class = get_class_definition();
_ref_count = 1;
browser->retainobject(_npobj);
}
@ -88,6 +84,7 @@ PPBrowserObject(const PPBrowserObject &copy) :
_npobj(copy._npobj)
{
_class = get_class_definition();
_ref_count = 1;
browser->retainobject(_npobj);
}
@ -98,6 +95,7 @@ PPBrowserObject(const PPBrowserObject &copy) :
////////////////////////////////////////////////////////////////////
PPBrowserObject::
~PPBrowserObject() {
assert(_ref_count == 0);
browser->releaseobject(_npobj);
}
@ -162,7 +160,6 @@ set_property(const string &property, P3D_object *value) {
result = browser->setproperty(_instance->get_npp_instance(), _npobj,
property_name, &npvalue);
browser->releasevariantvalue(&npvalue);
P3D_OBJECT_FINISH(value);
} else {
// Delete the property.
@ -268,7 +265,6 @@ get_class_definition() {
// appropriate pointers.
_browser_object_class = P3D_make_class_definition();
_browser_object_class->_finish = &object_finish;
_browser_object_class->_copy = &object_copy;
_browser_object_class->_get_repr = &object_get_repr;
_browser_object_class->_get_property = &object_get_property;

View File

@ -501,7 +501,7 @@ get_panda_script_object() {
// NPVariant, and stores it in result.
////////////////////////////////////////////////////////////////////
void PPInstance::
p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
p3dobj_to_variant(NPVariant *result, P3D_object *object) {
switch (P3D_OBJECT_GET_TYPE(object)) {
case P3D_OT_undefined:
VOID_TO_NPVARIANT(*result);
@ -534,7 +534,7 @@ p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
case P3D_OT_object:
{
PPPandaObject *ppobj = PPPandaObject::make_new(this, P3D_OBJECT_COPY(object));
PPPandaObject *ppobj = PPPandaObject::make_new(this, object);
OBJECT_TO_NPVARIANT(ppobj, *result);
}
break;
@ -571,7 +571,7 @@ variant_to_p3dobj(const NPVariant *variant) {
PPPandaObject *ppobject = (PPPandaObject *)object;
P3D_object *obj = ppobject->get_p3d_object();
logfile << "Found nested Panda Object " << obj << "\n" << flush;
return P3D_OBJECT_COPY(obj);
return obj;
}
// It's a generic NPObject of some kind.
@ -899,7 +899,7 @@ create_instance() {
logfile << "Couldn't get window_object\n" << flush;
}
const P3D_token *tokens = NULL;
P3D_token *tokens = NULL;
if (!_tokens.empty()) {
tokens = &_tokens[0];
}

View File

@ -55,7 +55,7 @@ public:
NPObject *get_panda_script_object();
void p3dobj_to_variant(NPVariant *result, const P3D_object *object);
void p3dobj_to_variant(NPVariant *result, P3D_object *object);
P3D_object *variant_to_p3dobj(const NPVariant *variant);
static void output_np_variant(ostream &out, const NPVariant &result);

View File

@ -18,8 +18,12 @@
// Access: Public
// Description: Returns the p3d_object this PPPandaObject maps to. This
// may be NULL if the object is not fully initialized.
// If not NULL, this returns a new reference.
////////////////////////////////////////////////////////////////////
inline P3D_object *PPPandaObject::
get_p3d_object() const {
if (_p3d_object != NULL) {
P3D_OBJECT_INCREF(_p3d_object);
}
return _p3d_object;
}

View File

@ -53,16 +53,17 @@ make_new(PPInstance *inst, P3D_object *p3d_object) {
// Function: PPPandaObject::set_p3d_object
// Access: Public
// Description: Changes the p3d_object this PPPandaObject maps to. The
// previous object, if any, is deleted. Ownership of
// the new object is passed to the PPPandaObject.
// new object's reference count is incremented, and the
// previous object's is decremented.
////////////////////////////////////////////////////////////////////
void PPPandaObject::
set_p3d_object(P3D_object *p3d_object) {
if (_p3d_object != p3d_object) {
if (_p3d_object != NULL) {
P3D_OBJECT_FINISH(_p3d_object);
}
P3D_OBJECT_XDECREF(_p3d_object);
_p3d_object = p3d_object;
if (_p3d_object != NULL) {
P3D_OBJECT_INCREF(_p3d_object);
}
}
}
@ -78,7 +79,8 @@ void PPPandaObject::
construct(PPInstance *inst, P3D_object *p3d_object) {
logfile << "construct: " << this << "\n" << flush;
_instance = inst;
_p3d_object = p3d_object;
_p3d_object = NULL;
set_p3d_object(p3d_object);
}
////////////////////////////////////////////////////////////////////
@ -141,12 +143,16 @@ invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount,
}
P3D_object **p3dargs = new P3D_object *[argCount];
for (unsigned int i = 0; i < argCount; ++i) {
unsigned int i;
for (i = 0; i < argCount; ++i) {
p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
}
P3D_object *value = P3D_OBJECT_CALL(_p3d_object, method_name.c_str(),
p3dargs, argCount);
for (i = 0; i < argCount; ++i) {
P3D_OBJECT_DECREF(p3dargs[i]);
}
delete[] p3dargs;
if (value == NULL) {
@ -156,7 +162,7 @@ invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount,
// We have the return value, and its value is stored in value.
_instance->p3dobj_to_variant(result, value);
P3D_OBJECT_FINISH(value);
P3D_OBJECT_DECREF(value);
return true;
}
@ -177,12 +183,16 @@ invoke_default(const NPVariant *args, uint32_t argCount,
}
P3D_object **p3dargs = new P3D_object *[argCount];
for (unsigned int i = 0; i < argCount; ++i) {
unsigned int i;
for (i = 0; i < argCount; ++i) {
p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
}
P3D_object *value = P3D_OBJECT_CALL(_p3d_object, "",
p3dargs, argCount);
for (i = 0; i < argCount; ++i) {
P3D_OBJECT_DECREF(p3dargs[i]);
}
delete[] p3dargs;
if (value == NULL) {
@ -192,7 +202,7 @@ invoke_default(const NPVariant *args, uint32_t argCount,
// We have the return value, and its value is stored in value.
_instance->p3dobj_to_variant(result, value);
P3D_OBJECT_FINISH(value);
P3D_OBJECT_DECREF(value);
return true;
}
@ -239,7 +249,7 @@ get_property(NPIdentifier name, NPVariant *result) {
// We have the property, and its value is stored in value.
_instance->p3dobj_to_variant(result, value);
P3D_OBJECT_FINISH(value);
P3D_OBJECT_DECREF(value);
return true;
}
@ -260,6 +270,7 @@ set_property(NPIdentifier name, const NPVariant *value) {
P3D_object *object = _instance->variant_to_p3dobj(value);
bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
P3D_OBJECT_DECREF(object);
return result;
}