Various substantial changes to Interrogate:

* Allow arbitrary selection of optional keyword arguments in some cases
* Reduce code bloat of generated bindings
* Work around awkward resolution of set_shader_input overloads
* Document the code a bit better
* Make coercion a bit cleaner for reference counted types
* A few optimization tweaks
* Use generic errors in NDEBUG build to reduce size of string pool
This commit is contained in:
rdb 2015-02-15 13:48:13 +01:00
parent d43068b09a
commit 9513046e59
26 changed files with 1634 additions and 552 deletions

View File

@ -147,6 +147,30 @@ as_pointer() const {
}
}
////////////////////////////////////////////////////////////////////
// Function: CPPExpression::Result::as_boolean
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
bool CPPExpression::Result::
as_boolean() const {
switch (_type) {
case RT_integer:
return (_u._integer != 0);
case RT_real:
return (_u._real != 0.0);
case RT_pointer:
return (_u._pointer != NULL);
default:
cerr << "Invalid type\n";
assert(false);
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: CPPExpression::Result::output
// Access: Public
@ -1098,8 +1122,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
break;
case T_variable:
// We can just refer to the variable by name, except if it's a
// private constant, in which case we have to compute the value,
// since we may have to use it in generated code.
if (_u._variable->_type != NULL &&
_u._variable->_initializer != NULL) {
_u._variable->_initializer != NULL &&
_u._variable->_vis > V_public) {
// A const variable. Fetch its assigned value.
CPPConstType *const_type = _u._variable->_type->as_const_type();
if (const_type != NULL) {
@ -1536,4 +1564,3 @@ is_less(const CPPDeclaration *other) const {
return false;
}

View File

@ -63,6 +63,7 @@ public:
int as_integer() const;
double as_real() const;
void *as_pointer() const;
bool as_boolean() const;
void output(ostream &out) const;
ResultType _type;

View File

@ -796,9 +796,14 @@ get_local_name(CPPScope *scope) const {
}
*/
if (scope != NULL && _parent_scope != NULL && _parent_scope != scope) {
return _parent_scope->get_local_name(scope) + "::" +
_name.get_name_with_templ();
if (scope != NULL && _parent_scope != NULL/* && _parent_scope != scope*/) {
string parent_scope_name = _parent_scope->get_local_name(scope);
if (parent_scope_name.empty()) {
return _name.get_name_with_templ();
} else {
return parent_scope_name + "::" +
_name.get_name_with_templ();
}
} else {
return _name.get_name_with_templ();
}
@ -1040,6 +1045,10 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
(*vi).second->substitute_decl(subst, to_scope, global_scope)->as_instance();
to_scope->_variables.insert(Variables::value_type((*vi).first, inst));
if (inst != (*vi).second) {
// I don't know if this _native_scope assignment is right, but it
// fixes some issues with variables in instantiated template scopes
// being printed out with an uninstantiated template scope prefix. ~rdb
inst->_ident->_native_scope = to_scope;
anything_changed = true;
}
}
@ -1126,6 +1135,13 @@ handle_declaration(CPPDeclaration *decl, CPPScope *global_scope,
if (inst != NULL) {
inst->check_for_constructor(this, global_scope);
if (inst->_ident != NULL) {
// Not sure if this is the best place to assign this. However,
// this fixes a bug with variables in expressions not having
// the proper scoping prefix. ~rdb
inst->_ident->_native_scope = this;
}
string name = inst->get_simple_name();
if (!name.empty() && inst->get_scope(this, global_scope) == this) {
if (inst->_type->as_function_type()) {

View File

@ -200,7 +200,7 @@ call_function(ostream &out, int indent_level, bool convert_result,
// Now a simple special-case test. Often, we will have converted
// the reference-returning assignment operator to a pointer. In
// this case, we might inadventent generate code like "return
// this case, we might inadvertently generate code like "return
// &(*this)", when "return this" would do. We check for this here
// and undo it as a special case.
@ -234,8 +234,14 @@ call_function(ostream &out, int indent_level, bool convert_result,
&parser);
out << " = " << call << ";\n";
// MOVE() expands to std::move() when we are compiling with a
// compiler that supports rvalue references. It basically turns
// an lvalue into an rvalue, allowing a move constructor to be
// called instead of a copy constructor (since we won't be using
// the return value any more), which is usually more efficient if
// it exists. If it doesn't, it shouldn't do any harm.
string new_str =
_return_type->prepare_return_expr(out, indent_level, "result");
_return_type->prepare_return_expr(out, indent_level, "MOVE(result)");
return_expr = _return_type->get_return_expr(new_str);
} else {
@ -258,11 +264,11 @@ call_function(ostream &out, int indent_level, bool convert_result,
// comment.
////////////////////////////////////////////////////////////////////
void FunctionRemap::
write_orig_prototype(ostream &out, int indent_level, bool local) const {
write_orig_prototype(ostream &out, int indent_level, bool local, int num_default_args) const {
if (local) {
_cppfunc->output(out, indent_level, NULL, false, _num_default_parameters);
_cppfunc->output(out, indent_level, NULL, false, num_default_args);
} else {
_cppfunc->output(out, indent_level, &parser, false, _num_default_parameters);
_cppfunc->output(out, indent_level, &parser, false, num_default_args);
}
}
@ -426,7 +432,7 @@ get_call_str(const string &container, const vector_string &pexprs) const {
}
int pn = _first_true_parameter;
int num_parameters = _parameters.size();
int num_parameters = pexprs.size();
if (_type == T_item_assignment_operator) {
// The last parameter is the value to set.
@ -716,7 +722,8 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
if ((int)_parameters.size() == first_param) {
_args_type = InterfaceMaker::AT_no_args;
} else if ((int)_parameters.size() == first_param + 1) {
} else if ((int)_parameters.size() == first_param + 1 &&
_parameters[first_param]._remap->get_default_value() == NULL) {
_args_type = InterfaceMaker::AT_single_arg;
} else {
_args_type = InterfaceMaker::AT_varargs;

View File

@ -52,11 +52,12 @@ public:
~FunctionRemap();
string get_parameter_name(int n) const;
string call_function(ostream &out, int indent_level,
string call_function(ostream &out, int indent_level,
bool convert_result, const string &container,
const vector_string &pexprs = vector_string()) const;
void write_orig_prototype(ostream &out, int indent_level, bool local=false) const;
void write_orig_prototype(ostream &out, int indent_level, bool local=false,
int num_default_args=0) const;
FunctionWrapperIndex make_wrapper_entry(FunctionIndex function_index);

View File

@ -871,6 +871,12 @@ delete_return_value(ostream &out, int indent_level,
void InterfaceMaker::
output_ref(ostream &out, int indent_level, FunctionRemap *remap,
const string &varname) const {
if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) {
// Actually, we have it stored in a PointerTo. No need to do anything.
return;
}
if (remap->_type == FunctionRemap::T_constructor ||
remap->_type == FunctionRemap::T_typecast) {
// In either of these cases, we can safely assume the pointer will
@ -901,6 +907,12 @@ output_ref(ostream &out, int indent_level, FunctionRemap *remap,
void InterfaceMaker::
output_unref(ostream &out, int indent_level, FunctionRemap *remap,
const string &varname) const {
if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) {
// Actually, we have it stored in a PointerTo. No need to do anything.
return;
}
if (remap->_type == FunctionRemap::T_constructor ||
remap->_type == FunctionRemap::T_typecast) {
// In either of these cases, we can safely assume the pointer will

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,7 @@ public:
virtual void write_sub_module(ostream &out, Object *obj);
virtual bool synthesize_this_parameter();
virtual bool separate_overloading();
virtual Object *record_object(TypeIndex type_index);
@ -127,15 +128,21 @@ private:
ArgsType args_type, int return_flags);
void write_coerce_constructor(ostream &out, Object *obj, bool is_const);
int collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
int max_required_args);
void write_function_forset(ostream &out,
const std::set<FunctionRemap*> &remaps,
int min_num_args, int max_num_args,
string &expected_params, int indent_level,
bool coercion_allowed, bool report_errors,
ArgsType args_type, int return_flags,
bool check_exceptions = true,
bool verify_const = false,
const string &first_expr = string());
void write_function_instance(ostream &out, FunctionRemap *remap,
int min_num_args, int max_num_args,
string &expected_params, int indent_level,
bool coercion_allowed, bool report_errors,
ArgsType args_type, int return_flags,
@ -144,7 +151,7 @@ private:
void error_return(ostream &out, int indent_level, int return_flags);
void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
const std::string &return_expr);
std::string return_expr);
void write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
MakeSeq *make_seq);

View File

@ -670,7 +670,11 @@ bool TypeManager::
is_const_char_pointer(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_char_pointer(type->as_const_type()->_wrapped_around);
return is_const_char_pointer(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_pointer:
return (is_const(type->as_pointer_type()->_pointing_at) &&
is_char(type->as_pointer_type()->_pointing_at));
case CPPDeclaration::ST_typedef:
return is_const_char_pointer(type->as_typedef_type()->_type);

View File

@ -19,16 +19,20 @@
PyMemberDef standard_type_members[] = {
{(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
// {(char *)"this_ownership", T_INT, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
// {(char *)"this_const", T_INT, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"},
{(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
{(char *)"this_const", T_BOOL, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"},
// {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature), READONLY, (char *)"A type check signature"},
{(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"},
{NULL} /* Sentinel */
};
////////////////////////////////////////////////////////////////////////
/// Simple Recognition Functions..
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: DtoolCanThisBeAPandaInstance
// Description: Given a valid (non-NULL) PyObject, does a simple
// check to see if it might be an instance of a Panda
// type. It does this using a signature that is
// encoded on each instance.
////////////////////////////////////////////////////////////////////
bool DtoolCanThisBeAPandaInstance(PyObject *self) {
// simple sanity check for the class type..size.. will stop basic foobars..
// It is arguably better to use something like this:
@ -58,6 +62,53 @@ void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *c
}
}
////////////////////////////////////////////////////////////////////
// Function: Dtool_Call_ExtractThisPointer
// Description: This is a support function for the Python bindings:
// it extracts the underlying C++ pointer of the given
// type for a given Python object. If it was of the
// wrong type, raises an AttributeError.
////////////////////////////////////////////////////////////////////
bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer) {
if (self != NULL && DtoolCanThisBeAPandaInstance(self)) {
*answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
return true;
}
PyErr_SetString(PyExc_AttributeError, "C++ object is not yet constructed, or already destructed.");
return false;
}
////////////////////////////////////////////////////////////////////
// Function: Dtool_Call_ExtractThisPointer_NonConst
// Description: The same thing as Dtool_Call_ExtractThisPointer,
// except that it performs the additional check that
// the pointer is a non-const pointer. This is called
// by function wrappers for functions of which all
// overloads are non-const, and saves a bit of code.
//
// The extra method_name argument is used in formatting
// the error message.
////////////////////////////////////////////////////////////////////
bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
void **answer, const char *method_name) {
if (self != NULL && DtoolCanThisBeAPandaInstance(self)) {
*answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
return true;
}
if (((Dtool_PyInstDef *)self)->_is_const) {
// All overloads of this function are non-const.
PyErr_Format(PyExc_TypeError,
"Cannot call %s() on a const object.",
method_name);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DTOOL_Call_GetPointerThisClass
// Description: Extracts the C++ pointer for an object, given its
@ -118,12 +169,8 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
}
if (report_errors) {
PyTypeObject *tp = Py_TYPE(self);
PyErr_Format(PyExc_TypeError,
"%s() argument %d must be %s, not %s",
function_name.c_str(), param,
classdef->_PyType.tp_name, tp->tp_name);
Dtool_Raise_ArgTypeError(self, param, function_name.c_str(), classdef->_PyType.tp_name);
return NULL;
}
return NULL;
@ -140,6 +187,48 @@ void *DTOOL_Call_GetPointerThis(PyObject *self) {
return NULL;
}
#ifndef NDEBUG
////////////////////////////////////////////////////////////////////
// Function: Dtool_CheckErrorOccurred
// Description: This is similar to a PyErr_Occurred() check, except
// that it also checks Notify to see if an assertion
// has occurred. If that is the case, then it raises
// an AssertionError.
//
// Returns true if there is an active exception, false
// otherwise.
//
// In the NDEBUG case, this is simply a #define to
// _PyErr_OCCURRED() (which is an undocumented inline
// version of PyErr_Occurred()).
////////////////////////////////////////////////////////////////////
bool Dtool_CheckErrorOccurred() {
if (_PyErr_OCCURRED()) {
return true;
}
Notify *notify = Notify::ptr();
if (notify->has_assert_failed()) {
PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());
notify->clear_assert_failed();
return true;
}
return false;
}
#endif // NDEBUG
////////////////////////////////////////////////////////////////////
// Function: Dtool_Raise_ArgTypeError
// Description: Raises a TypeError of the form:
// function_name() argument n must be type, not type
// for a given object passed to a function.
////////////////////////////////////////////////////////////////////
void Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name) {
PyErr_Format(PyExc_TypeError,
"%s() argument %d must be %s, not %s",
function_name, param, type_name,
Py_TYPE(obj)->tp_name);
}
////////////////////////////////////////////////////////////////////////
// Function : DTool_CreatePyInstanceTyped
//

View File

@ -110,6 +110,7 @@ inline PyObject* doPy_RETURN_FALSE()
#define nb_divide nb_true_divide
#define nb_inplace_divide nb_inplace_true_divide
#define PyLongOrInt_Check(x) PyLong_Check(x)
#define PyLongOrInt_FromSize_t PyLong_FromSize_t
#define PyLongOrInt_FromLong PyLong_FromLong
#define PyLongOrInt_FromUnsignedLong PyLong_FromUnsignedLong
@ -117,6 +118,7 @@ inline PyObject* doPy_RETURN_FALSE()
#define PyInt_AsLong PyLong_Aslong
#define PyInt_AS_LONG PyLong_AS_LONG
#else
#define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
// PyInt_FromSize_t automatically picks the right type.
#define PyLongOrInt_FromSize_t PyInt_FromSize_t
#define PyLongOrInt_FromLong PyInt_FromLong
@ -160,14 +162,26 @@ typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *);
////////////////////////////////////////////////////////////////////////
// THIS IS THE INSTANCE CONTAINER FOR ALL panda py objects....
////////////////////////////////////////////////////////////////////////
// this should save 8 bytes per object ....
struct Dtool_PyInstDef {
PyObject_HEAD
// Pointer to the underlying C++ object.
void *_ptr_to_object;
// This is a pointer to the Dtool_PyTypedObject type. It's tempting
// not to store this and to instead use PY_TYPE(self) and upcast that,
// but that breaks when someone inherits from our class in Python.
struct Dtool_PyTypedObject *_My_Type;
// This is always set to PY_PANDA_SIGNATURE, so that we can quickly
// detect whether an object is a Panda object.
unsigned short _signature;
int _memory_rules : 1; // true if we own the pointer and should delete it or unref it
int _is_const : 1; // true if this is a "const" pointer.
// True if we own the pointer and should delete it or unref it.
bool _memory_rules;
// True if this is a "const" pointer.
bool _is_const;
};
////////////////////////////////////////////////////////////////////////
@ -345,6 +359,11 @@ EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyT
EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThis(PyObject *self);
EXPCL_DTOOLCONFIG bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
EXPCL_DTOOLCONFIG bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
void **answer, const char *method_name);
template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) {
if (DtoolCanThisBeAPandaInstance(self)) {
Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
@ -357,6 +376,17 @@ template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&
return false;
}
// Functions related to error reporting.
#ifdef NDEBUG
// _PyErr_OCCURRED is an undocumented inline version of PyErr_Occurred.
#define Dtool_CheckErrorOccurred() (_PyErr_OCCURRED() != NULL)
#else
EXPCL_DTOOLCONFIG bool Dtool_CheckErrorOccurred();
#endif
EXPCL_DTOOLCONFIG void Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name);
////////////////////////////////////////////////////////////////////////
// Function : DTool_CreatePyInstanceTyped
//

View File

@ -33,6 +33,21 @@ class PyThreadState;
typedef int Py_ssize_t;
struct Py_buffer;
// We need to define these accurately since interrogate may want to
// write these out to default value assignments.
PyObject _Py_NoneStruct;
PyObject _Py_TrueStruct;
#define Py_None (&_Py_NoneStruct)
#define Py_True ((PyObject *) &_Py_TrueStruct)
#if PY_MAJOR_VERSION >= 3
PyObject _Py_ZeroStruct;
#define Py_False ((PyObject *) &_Py_ZeroStruct)
#else
PyObject _Py_FalseStruct;
#define Py_False ((PyObject *) &_Py_FalseStruct)
#endif
// This file defines PY_VERSION_HEX, which is used in some places.
#include "patchlevel.h"

View File

@ -36,6 +36,13 @@ __published:
};
enum openmode {
};
// Don't define these lest interrogate get tempted to actually
// substitute in the values, which are implementation-defined.
static const openmode app;
static const openmode binary;
static const openmode in;
static const openmode out;
static const openmode trunc;
};
class ios : public ios_base {
__published:

View File

@ -38,7 +38,11 @@ typedef unsigned long ulong;
typedef unsigned short ushort;
typedef unsigned char uchar;
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
typedef int fd_set;

View File

@ -26,7 +26,7 @@ template<class ctype>
class basic_string {
public:
typedef typename size_t size_type;
static const size_t npos = (size_t)-1;
static const size_t npos;
basic_string();
basic_string(const basic_string &copy);

View File

@ -182,54 +182,6 @@ get_assert_handler() const {
return _assert_handler;
}
////////////////////////////////////////////////////////////////////
// Function: Notify::has_assert_failed
// Access: Public
// Description: Returns true if an assertion test has failed (and not
// been ignored) since the last call to
// clear_assert_failed().
//
// When an assertion test fails, the assert handler
// may decide either to abort, return, or ignore the
// assertion. Naturally, if it decides to abort, this
// flag is irrelevant. If it chooses to ignore the
// assertion, the flag is not set. However, if the
// assert handler chooses to return out of the
// function (the normal case), it will also set this
// flag to indicate that an assertion failure has
// occurred.
//
// This will also be the behavior in the absence of a
// user-defined assert handler.
////////////////////////////////////////////////////////////////////
bool Notify::
has_assert_failed() const {
return _assert_failed;
}
////////////////////////////////////////////////////////////////////
// Function: Notify::get_assert_error_message
// Access: Public
// Description: Returns the error message that corresponds to the
// assertion that most recently failed.
////////////////////////////////////////////////////////////////////
const string &Notify::
get_assert_error_message() const {
return _assert_error_message;
}
////////////////////////////////////////////////////////////////////
// Function: Notify::clear_assert_failed
// Access: Public
// Description: Resets the assert_failed flag that is set whenever an
// assertion test fails. See has_assert_failed().
////////////////////////////////////////////////////////////////////
void Notify::
clear_assert_failed() {
_assert_failed = false;
}
////////////////////////////////////////////////////////////////////
// Function: Notify::get_top_category
// Access: Public
@ -269,7 +221,7 @@ get_category(const string &basename, NotifyCategory *parent_category) {
}
}
pair<Categories::iterator, bool> result =
pair<Categories::iterator, bool> result =
_categories.insert(Categories::value_type(fullname, (NotifyCategory *)NULL));
bool inserted = result.second;
@ -458,7 +410,7 @@ assert_failure(const char *expression, int line,
// the debugger? abort() doesn't do it. We used to be able to
// assert(false), but in VC++ 7 that just throws an exception, and
// an uncaught exception just exits, without offering to open the
// debugger.
// debugger.
// DebugBreak() seems to be provided for this purpose, but it
// doesn't seem to work properly either, since we don't seem to
@ -567,7 +519,7 @@ config_initialized() {
dup2(logfile_fd, STDOUT_FILENO);
dup2(logfile_fd, STDERR_FILENO);
close(logfile_fd);
set_ostream_ptr(&cerr, false);
}
#else

View File

@ -12,3 +12,50 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Notify::has_assert_failed
// Access: Public
// Description: Returns true if an assertion test has failed (and not
// been ignored) since the last call to
// clear_assert_failed().
//
// When an assertion test fails, the assert handler
// may decide either to abort, return, or ignore the
// assertion. Naturally, if it decides to abort, this
// flag is irrelevant. If it chooses to ignore the
// assertion, the flag is not set. However, if the
// assert handler chooses to return out of the
// function (the normal case), it will also set this
// flag to indicate that an assertion failure has
// occurred.
//
// This will also be the behavior in the absence of a
// user-defined assert handler.
////////////////////////////////////////////////////////////////////
INLINE bool Notify::
has_assert_failed() const {
return _assert_failed;
}
////////////////////////////////////////////////////////////////////
// Function: Notify::get_assert_error_message
// Access: Public
// Description: Returns the error message that corresponds to the
// assertion that most recently failed.
////////////////////////////////////////////////////////////////////
INLINE const string &Notify::
get_assert_error_message() const {
return _assert_error_message;
}
////////////////////////////////////////////////////////////////////
// Function: Notify::clear_assert_failed
// Access: Public
// Description: Resets the assert_failed flag that is set whenever an
// assertion test fails. See has_assert_failed().
////////////////////////////////////////////////////////////////////
INLINE void Notify::
clear_assert_failed() {
_assert_failed = false;
}

View File

@ -51,9 +51,9 @@ PUBLISHED:
bool has_assert_handler() const;
AssertHandler *get_assert_handler() const;
bool has_assert_failed() const;
const string &get_assert_error_message() const;
void clear_assert_failed();
INLINE bool has_assert_failed() const;
INLINE const string &get_assert_error_message() const;
INLINE void clear_assert_failed();
NotifyCategory *get_top_category();
NotifyCategory *get_category(const string &basename,

View File

@ -194,6 +194,7 @@ extern "C" {
EXPCL_PYSTUB extern void *PyExc_SystemExit;
EXPCL_PYSTUB extern void *PyExc_TypeError;
EXPCL_PYSTUB extern void *PyExc_ValueError;
EXPCL_PYSTUB extern void *_PyThreadState_Current;
EXPCL_PYSTUB extern void *_Py_FalseStruct;
EXPCL_PYSTUB extern void *_Py_NoneStruct;
EXPCL_PYSTUB extern void *_Py_NotImplementedStruct;
@ -386,6 +387,7 @@ void *PyExc_StopIteration = (void *)NULL;
void *PyExc_SystemExit = (void *)NULL;
void *PyExc_TypeError = (void *)NULL;
void *PyExc_ValueError = (void *)NULL;
void *_PyThreadState_Current = (void *)NULL;
void *_Py_FalseStruct = (void *)NULL;
void *_Py_NoneStruct = (void *)NULL;
void *_Py_NotImplementedStruct = (void *)NULL;

View File

@ -84,7 +84,7 @@ get_raw_pointer() const {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_device_index
// Access: Public
// Description: Set the device index. This is reported in pointer
// Description: Set the device index. This is reported in pointer
// events. The device index will be equal to the position
// of the GraphicsWindowInputDevice in the window's list.
////////////////////////////////////////////////////////////////////
@ -117,9 +117,116 @@ disable_pointer_events() {
_pointer_events.clear();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_down
// Access: Published
// Description: Records that the indicated button has been depressed.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
button_down(ButtonHandle button) {
button_down(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_resume_down
// Access: Published
// Description: Records that the indicated button was depressed
// earlier, and we only just detected the event after
// the fact. This is mainly useful for tracking the
// state of modifier keys.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
button_resume_down(ButtonHandle button) {
button_resume_down(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_up
// Access: Published
// Description: Records that the indicated button has been released.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
button_up(ButtonHandle button) {
button_up(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::keystroke
// Access: Published
// Description: Records that the indicated keystroke has been
// generated.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
keystroke(int keycode) {
keystroke(keycode, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::focus_lost
// Access: Published
// Description: This should be called when the window focus is lost,
// so that we may miss upcoming button events
// (especially "up" events) for the next period of time.
// It generates keyboard and mouse "up" events for those
// buttons that we previously sent unpaired "down"
// events, so that the Panda application will believe
// all buttons are now released.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
focus_lost() {
focus_lost(ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::raw_button_down
// Access: Published
// Description: Records that the indicated button has been depressed.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
raw_button_down(ButtonHandle button) {
raw_button_down(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::raw_button_up
// Access: Published
// Description: Records that the indicated button has been released.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
raw_button_up(ButtonHandle button) {
raw_button_up(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_in_window
// Access: Public
// Access: Published
// Description: To be called by a particular kind of GraphicsWindow
// to indicate that the pointer is within the window, at
// the given pixel coordinates.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_pointer_in_window(double x, double y) {
// mutex is handled in set pointer .. convience function
set_pointer(true, x, y, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_out_of_window
// Access: Published
// Description: To be called by a particular kind of GraphicsWindow
// to indicate that the pointer is no longer within the
// window.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_pointer_out_of_window() {
// mutex is handled in set pointer .. convience function
set_pointer(false, _mouse_data._xpos, _mouse_data._ypos,
ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_in_window
// Access: Published
// Description: To be called by a particular kind of GraphicsWindow
// to indicate that the pointer is within the window, at
// the given pixel coordinates.
@ -132,7 +239,7 @@ set_pointer_in_window(double x, double y, double time) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_out_of_window
// Access: Public
// Access: Published
// Description: To be called by a particular kind of GraphicsWindow
// to indicate that the pointer is no longer within the
// window.

View File

@ -94,7 +94,7 @@ pointer_and_keyboard(GraphicsWindow *host, const string &name) {
// Description:
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice::
GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
{
*this = copy;
}
@ -105,7 +105,7 @@ GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
// Description:
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
operator = (const GraphicsWindowInputDevice &copy)
operator = (const GraphicsWindowInputDevice &copy)
{
LightMutexHolder holder(_lock);
LightMutexHolder holder1(copy._lock);
@ -165,7 +165,7 @@ get_button_event() {
// Function: GraphicsWindowInputDevice::has_pointer_event
// Access: Public
// Description: Returns true if this device has a pending pointer
// event (a mouse movement), or false otherwise. If
// event (a mouse movement), or false otherwise. If
// this returns true, the particular event may be
// extracted via get_pointer_event().
////////////////////////////////////////////////////////////////////
@ -234,7 +234,7 @@ disable_pointer_mode() {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer
// Access: Public
// Access: Published
// Description: Records that a mouse movement has taken place.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
@ -264,7 +264,7 @@ set_pointer(bool inwin, double x, double y, double time) {
} else {
_mouse_data = _true_mouse_data;
}
if (_enable_pointer_events) {
int seq = _event_sequence++;
if (_pointer_events == 0) {
@ -279,7 +279,7 @@ set_pointer(bool inwin, double x, double y, double time) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_down
// Access: Public
// Access: Published
// Description: Records that the indicated button has been depressed.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
@ -291,7 +291,7 @@ button_down(ButtonHandle button, double time) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_resume_down
// Access: Public
// Access: Published
// Description: Records that the indicated button was depressed
// earlier, and we only just detected the event after
// the fact. This is mainly useful for tracking the
@ -300,14 +300,13 @@ button_down(ButtonHandle button, double time) {
void GraphicsWindowInputDevice::
button_resume_down(ButtonHandle button, double time) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time)
);
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time));
_buttons_held.insert(button);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_up
// Access: Public
// Access: Published
// Description: Records that the indicated button has been released.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
@ -319,7 +318,7 @@ button_up(ButtonHandle button, double time) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::keystroke
// Access: Public
// Access: Published
// Description: Records that the indicated keystroke has been
// generated.
////////////////////////////////////////////////////////////////////
@ -331,24 +330,24 @@ keystroke(int keycode, double time) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::candidate
// Access: Public
// Access: Published
// Description: Records that the indicated candidate string has been
// highlighted. This is used to implement IME support
// for typing in international languages, especially
// Chinese/Japanese/Korean.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
candidate(const wstring &candidate_string, size_t highlight_start,
candidate(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end, size_t cursor_pos) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(candidate_string,
_button_events.push_back(ButtonEvent(candidate_string,
highlight_start, highlight_end,
cursor_pos));
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::focus_lost
// Access: Public
// Access: Published
// Description: This should be called when the window focus is lost,
// so that we may miss upcoming button events
// (especially "up" events) for the next period of time.
@ -369,7 +368,7 @@ focus_lost(double time) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::raw_button_down
// Access: Public
// Access: Published
// Description: Records that the indicated button has been depressed.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
@ -380,7 +379,7 @@ raw_button_down(ButtonHandle button, double time) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::raw_button_up
// Access: Public
// Access: Published
// Description: Records that the indicated button has been released.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::

View File

@ -76,18 +76,28 @@ public:
PUBLISHED:
// The following interface is for the various kinds of
// GraphicsWindows to record the data incoming on the device.
void button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void button_resume_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void keystroke(int keycode, double time = ClockObject::get_global_clock()->get_frame_time());
void candidate(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end, size_t cursor_pos);
void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time());
void raw_button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void raw_button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE void button_down(ButtonHandle button);
INLINE void button_resume_down(ButtonHandle button);
INLINE void button_up(ButtonHandle button);
INLINE void keystroke(int keycode);
INLINE void focus_lost();
INLINE void raw_button_down(ButtonHandle button);
INLINE void raw_button_up(ButtonHandle button);
INLINE void set_pointer_in_window(double x, double y);
INLINE void set_pointer_out_of_window();
INLINE void set_pointer_in_window(double x, double y, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time());
void button_down(ButtonHandle button, double time);
void button_resume_down(ButtonHandle button, double time);
void button_up(ButtonHandle button, double time);
void keystroke(int keycode, double time);
void candidate(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end, size_t cursor_pos);
void focus_lost(double time);
void raw_button_down(ButtonHandle button, double time);
void raw_button_up(ButtonHandle button, double time);
INLINE void set_pointer_in_window(double x, double y, double time);
INLINE void set_pointer_out_of_window(double time);
void set_pointer(bool inwin, double x, double y, double time);
public:

View File

@ -109,6 +109,22 @@ operator T * () const {
return (To *)(this->_void_ptr);
}
////////////////////////////////////////////////////////////////////
// Function: PointerTo::cheat
// Access: Public
// Description: Returns a reference to the underlying pointer. This
// is a very unsafe method. It's only used by some
// interrogate code. If you think this method might be
// useful to you, you're probably wrong.
//
// Promise me you won't use this, okay?
////////////////////////////////////////////////////////////////////
template<class T>
INLINE T *&PointerTo<T>::
cheat() {
return (To *&)(this->_void_ptr);
}
////////////////////////////////////////////////////////////////////
// Function: PointerTo::p
// Access: Published
@ -274,13 +290,28 @@ operator -> () const {
// don't care which way it goes because either will be
// correct.
////////////////////////////////////////////////////////////////////
template<class T>
INLINE ConstPointerTo<T>::
operator const T * () const {
return (To *)(this->_void_ptr);
}
////////////////////////////////////////////////////////////////////
// Function: ConstPointerTo::cheat
// Access: Public
// Description: Returns a reference to the underlying pointer. This
// is a very unsafe method. It's only used by some
// interrogate code. If you think this method might be
// useful to you, you're probably wrong.
//
// Promise me you won't use this, okay?
////////////////////////////////////////////////////////////////////
template<class T>
INLINE const T *&ConstPointerTo<T>::
cheat() {
return (const To *&)(this->_void_ptr);
}
////////////////////////////////////////////////////////////////////
// Function: ConstPointerTo::p
// Access: Published

View File

@ -95,6 +95,8 @@ public:
// MSVC.NET 2005 insists that we use T *, and not To *, here.
INLINE operator T *() const;
INLINE T *&cheat();
PUBLISHED:
// When downcasting to a derived class from a PointerTo<BaseClass>,
// C++ would normally require you to cast twice: once to an actual
@ -160,6 +162,8 @@ public:
INLINE const To *operator -> () const;
INLINE operator const T *() const;
INLINE const T *&cheat();
PUBLISHED:
INLINE const To *p() const;

View File

@ -89,7 +89,7 @@ operator = (const ReferenceCount &) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCount::Destructor
// Access: Public, Virtual
// Description:
// Description:
////////////////////////////////////////////////////////////////////
ReferenceCount::
~ReferenceCount() {
@ -182,7 +182,7 @@ ref() const {
nassertv(test_ref_count_integrity());
#endif
AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
AtomicAdjust::inc(_ref_count);
}
////////////////////////////////////////////////////////////////////
@ -221,10 +221,9 @@ unref() const {
// directly? Are you sure you can't use PointerTo's?
nassertr(_ref_count > 0, 0);
#endif
return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
return AtomicAdjust::dec(_ref_count);
}
////////////////////////////////////////////////////////////////////
// Function: ReferenceCount::test_ref_count_integrity
// Access: Published
@ -360,7 +359,7 @@ unref_delete(RefCountType *ptr) {
if (!ptr->unref()) {
// If the reference count has gone to zero, delete the object.
delete ptr;
}
}
}
////////////////////////////////////////////////////////////////////

View File

@ -71,7 +71,7 @@ private:
void create_weak_list();
private:
enum {
enum {
// We use this value as a flag to indicate an object has been
// indicated as a local object, and should not be deleted except
// by its own destructor. Really, any nonzero value would do, but
@ -87,7 +87,7 @@ private:
deleted_ref_count = -100,
};
AtomicAdjust::Integer _ref_count;
mutable AtomicAdjust::Integer _ref_count;
AtomicAdjust::Pointer _weak_list; // WeakReferenceList *
public: