Add property support to interrogate (using MAKE_PROPERTY or using published members)

This commit is contained in:
rdb 2014-09-19 15:23:52 +00:00
parent 8afd8b1f57
commit c178aba639
22 changed files with 459 additions and 64 deletions

View File

@ -29,13 +29,7 @@
// on the mesh.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAAI AINode {
PUBLISHED:
// This variable specifies whether the node is an obtacle or not.
// Used for dynamic obstacle addition to the environment.
// obstacle = false
// navigational = true
bool _type;
public:
// This variable specifies the node status whether open, close
// or neutral.
// open = belongs to _open_list.
@ -48,6 +42,12 @@ PUBLISHED:
};
Status _status;
// This variable specifies whether the node is an obtacle or not.
// Used for dynamic obstacle addition to the environment.
// obstacle = false
// navigational = true
bool _type;
// The score is used to compute the traversal expense to nodes
// when using A*.
// _score = _cost + heuristic
@ -76,6 +76,7 @@ PUBLISHED:
// is written into navmesh.csv file.
AINode *_next;
PUBLISHED:
AINode(int grid_x, int grid_y, LVecBase3f pos, float w, float l, float h);
~AINode();

View File

@ -15,7 +15,7 @@
cppExpressionParser.h cppExtensionType.h cppFile.h \
cppFunctionGroup.h cppFunctionType.h cppGlobals.h \
cppIdentifier.h cppInstance.h cppInstanceIdentifier.h \
cppMakeSeq.h cppManifest.h \
cppMakeProperty.h cppMakeSeq.h cppManifest.h \
cppNameComponent.h cppNamespace.h \
cppParameterList.h cppParser.h cppPointerType.h \
cppPreprocessor.h cppReferenceType.h cppScope.h \
@ -31,7 +31,7 @@
cppExtensionType.cxx cppFile.cxx cppFunctionGroup.cxx \
cppFunctionType.cxx cppGlobals.cxx cppIdentifier.cxx \
cppInstance.cxx cppInstanceIdentifier.cxx \
cppMakeSeq.cxx cppManifest.cxx \
cppMakeProperty.cxx cppMakeSeq.cxx cppManifest.cxx \
cppNameComponent.cxx cppNamespace.cxx cppParameterList.cxx \
cppParser.cxx cppPointerType.cxx cppPreprocessor.cxx \
cppReferenceType.cxx cppScope.cxx cppSimpleType.cxx \

View File

@ -14,6 +14,7 @@
#include "cppEnumType.h"
#include "cppFunctionType.h"
#include "cppTBDType.h"
#include "cppMakeProperty.h"
#include "cppMakeSeq.h"
#include "cppParameterList.h"
#include "cppInstance.h"
@ -234,7 +235,6 @@ pop_struct() {
%token XOREQUAL
%token LSHIFTEQUAL
%token RSHIFTEQUAL
%token TOKENPASTE
%token KW_BEGIN_PUBLISH
%token KW_BLOCKING
@ -264,6 +264,7 @@ pop_struct() {
%token KW_INT
%token KW_LONG
%token KW_LONGLONG
%token KW_MAKE_PROPERTY
%token KW_MAKE_SEQ
%token KW_MUTABLE
%token KW_NAMESPACE
@ -475,7 +476,35 @@ declaration:
{
current_scope->set_current_vis(V_private);
}
| KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
| KW_MAKE_PROPERTY '(' IDENTIFIER ',' IDENTIFIER ')' ';'
{
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @1);
}
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), NULL, current_scope, @1.file);
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
}
| KW_MAKE_PROPERTY '(' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
{
CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @1);
}
CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @1);
}
CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
setter->as_function_group(),
current_scope, @1.file);
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
}
| KW_MAKE_SEQ '(' name ',' name ',' name ')' ';'
{
CPPMakeSeq *make_seq = new CPPMakeSeq($3->get_simple_name(), $5->get_simple_name(), $7->get_simple_name(), @1.file);
current_scope->add_declaration(make_seq, global_scope, current_lexer, @1);
@ -2086,7 +2115,7 @@ element:
| KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_CAST
| KW_STRUCT | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF | KW_TYPENAME
| KW_UNION | KW_UNSIGNED | KW_VIRTUAL | KW_VOID | KW_VOLATILE
| KW_WHILE | TOKENPASTE
| KW_WHILE
| KW_OPERATOR
{
}

View File

@ -356,6 +356,16 @@ as_type_proxy() {
return (CPPTypeProxy *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPDeclaration::as_make_property
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CPPMakeProperty *CPPDeclaration::
as_make_property() {
return (CPPMakeProperty *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPDeclaration::as_make_seq
// Access: Public, Virtual
@ -366,7 +376,6 @@ as_make_seq() {
return (CPPMakeSeq *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: CPPDeclaration::is_equal
// Access: Protected, Virtual

View File

@ -47,6 +47,7 @@ class CPPExtensionType;
class CPPStructType;
class CPPEnumType;
class CPPTypeProxy;
class CPPMakeProperty;
class CPPMakeSeq;
class CPPClassTemplateParameter;
class CPPTBDType;
@ -69,6 +70,7 @@ public:
ST_type,
ST_namespace,
ST_using,
ST_make_property,
ST_make_seq,
// Subtypes of CPPType
@ -136,6 +138,7 @@ public:
virtual CPPEnumType *as_enum_type();
virtual CPPTBDType *as_tbd_type();
virtual CPPTypeProxy *as_type_proxy();
virtual CPPMakeProperty *as_make_property();
virtual CPPMakeSeq *as_make_seq();
CPPVisibility _vis;
@ -154,8 +157,4 @@ operator << (ostream &out, const CPPDeclaration &decl) {
return out;
}
#endif

View File

@ -0,0 +1,99 @@
// Filename: cppMakeProperty.cxx
// Created by: rdb (18Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "cppMakeProperty.h"
#include "cppFunctionGroup.h"
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CPPMakeProperty::
CPPMakeProperty(CPPIdentifier *ident,
CPPFunctionGroup *getter, CPPFunctionGroup *setter,
CPPScope *current_scope, const CPPFile &file) :
CPPDeclaration(file),
_ident(ident),
_getter(getter),
_setter(setter)
{
_ident->_native_scope = current_scope;
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_simple_name
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
string CPPMakeProperty::
get_simple_name() const {
return _ident->get_simple_name();
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_local_name
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
string CPPMakeProperty::
get_local_name(CPPScope *scope) const {
return _ident->get_local_name(scope);
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_fully_scoped_name
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
string CPPMakeProperty::
get_fully_scoped_name() const {
return _ident->get_fully_scoped_name();
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void CPPMakeProperty::
output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
out << "__make_property(" << _ident->get_local_name(scope)
<< ", " << _getter->_name;
if (_setter != NULL) {
out << ", " << _setter->_name;
}
out << ");";
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::get_subtype
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CPPDeclaration::SubType CPPMakeProperty::
get_subtype() const {
return ST_make_property;
}
////////////////////////////////////////////////////////////////////
// Function: CPPMakeProperty::as_make_property
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CPPMakeProperty *CPPMakeProperty::
as_make_property() {
return this;
}

View File

@ -0,0 +1,51 @@
// Filename: cppMakeProperty.h
// Created by: rdb (18Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef CPPMAKEPROPERTY_H
#define CPPMAKEPROPERTY_H
#include "dtoolbase.h"
#include "cppDeclaration.h"
///////////////////////////////////////////////////////////////////
// Class : CPPMakeProperty
// Description : This is a MAKE_PROPERTY() declaration appearing
// within a class body. It means to generate a property
// within Python, replacing (for instance)
// get_something()/set_something() with a synthetic
// 'something' attribute.
////////////////////////////////////////////////////////////////////
class CPPMakeProperty : public CPPDeclaration {
public:
CPPMakeProperty(CPPIdentifier *ident,
CPPFunctionGroup *getter, CPPFunctionGroup *setter,
CPPScope *current_scope, const CPPFile &file);
virtual string get_simple_name() const;
virtual string get_local_name(CPPScope *scope = NULL) const;
virtual string get_fully_scoped_name() const;
virtual void output(ostream &out, int indent_level, CPPScope *scope,
bool complete) const;
virtual SubType get_subtype() const;
virtual CPPMakeProperty *as_make_property();
CPPIdentifier *_ident;
CPPFunctionGroup *_getter;
CPPFunctionGroup *_setter;
};
#endif

View File

@ -1987,6 +1987,7 @@ check_keyword(const string &name) {
if (name == "inline") return KW_INLINE;
if (name == "int") return KW_INT;
if (name == "long") return KW_LONG;
if (name == "__make_property") return KW_MAKE_PROPERTY;
if (name == "__make_seq") return KW_MAKE_SEQ;
if (name == "mutable") return KW_MUTABLE;
if (name == "namespace") return KW_NAMESPACE;

View File

@ -247,10 +247,6 @@ output(ostream &out) const {
out << "RSHIFTEQUAL";
break;
case TOKENPASTE:
out << "TOKENPASTE";
break;
case KW_BOOL:
out << "KW_BOOL";
break;

View File

@ -4,6 +4,7 @@
#include "cppCommentBlock.cxx"
#include "cppConstType.cxx"
#include "cppDeclaration.cxx"
#include "cppMakeProperty.cxx"
#include "cppMakeSeq.cxx"
#include "cppParameterList.cxx"
#include "cppParser.cxx"

View File

@ -397,17 +397,16 @@
#define BEGIN_PUBLISH __begin_publish
#define END_PUBLISH __end_publish
#define BLOCKING __blocking
#define MAKE_PROPERTY(property_name, ...) __make_property(property_name, __VA_ARGS__)
#define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
#undef USE_STL_ALLOCATOR /* Don't try to parse these template classes in interrogate. */
#define EXTENSION(x) __extension x
#define EXTEND __extension
#define EXT_FUNC(func) ::func()
#define EXT_FUNC_ARGS(func, ...) ::func(__VA_ARGS__)
#define CALL_EXT_FUNC(func, ...) ::func (__VA_ARGS__)
#else
#define BEGIN_PUBLISH
#define END_PUBLISH
#define BLOCKING
#define MAKE_PROPERTY(property_name, ...)
#define MAKE_SEQ(seq_name, num_name, element_name)
#define EXTENSION(x)
#define EXTEND

View File

@ -371,7 +371,8 @@ get_call_str(const string &container, const vector_string &pexprs) const {
}
call << " = ";
_parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs));
_parameters[_first_true_parameter]._remap->pass_parameter(call,
get_parameter_expr(_first_true_parameter, pexprs));
} else {
const char *separator = "";

View File

@ -87,6 +87,19 @@ MakeSeq(const string &name, CPPMakeSeq *cpp_make_seq) :
{
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::Property::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
InterfaceMaker::Property::
Property(const InterrogateElement &ielement) :
_ielement(ielement),
_getter(NULL),
_setter(NULL)
{
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::Object::Constructor
// Access: Public
@ -156,6 +169,8 @@ check_protocols() {
_protocol_types |= PT_iter;
}
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
// Now are there any make_seq requests within this class?
if (_itype._cpptype != NULL) {
CPPStructType *stype = _itype._cpptype->as_struct_type();
@ -230,9 +245,9 @@ InterfaceMaker::
Object *object = (*oi).second;
delete object;
}
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
delete (*fi);
delete (*fi).second;
}
}
@ -501,9 +516,9 @@ wrap_global_functions() {
////////////////////////////////////////////////////////////////////
void InterfaceMaker::
get_function_remaps(vector<FunctionRemap *> &remaps) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
Function::Remaps::const_iterator ri;
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
FunctionRemap *remap = (*ri);
@ -617,12 +632,17 @@ get_unique_prefix() {
////////////////////////////////////////////////////////////////////
InterfaceMaker::Function *InterfaceMaker::
record_function(const InterrogateType &itype, FunctionIndex func_index) {
if (_functions.count(func_index)) {
// Already exists.
return _functions[func_index];
}
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
const InterrogateFunction &ifunc = idb->get_function(func_index);
string wrapper_name = get_wrapper_name(itype, ifunc, func_index);
Function *func = new Function(wrapper_name, itype, ifunc);
_functions.push_back(func);
_functions[func_index] = func;
// printf(" Function Name = %s\n", ifunc.get_name().c_str());

View File

@ -29,8 +29,9 @@ class ParameterRemap;
class CPPType;
class CPPInstance;
class InterrogateBuilder;
class InterrogateType;
class InterrogateElement;
class InterrogateFunction;
class InterrogateType;
////////////////////////////////////////////////////////////////////
// Class : InterfaceMaker
@ -107,8 +108,9 @@ public:
int _flags;
ArgsType _args_type;
};
typedef map<FunctionIndex, Function *> FunctionsByIndex;
typedef vector<Function *> Functions;
Functions _functions;
FunctionsByIndex _functions;
class MakeSeq {
public:
@ -121,6 +123,16 @@ public:
};
typedef vector<MakeSeq *> MakeSeqs;
class Property {
public:
Property(const InterrogateElement &ielement);
const InterrogateElement &_ielement;
Function *_getter;
Function *_setter;
};
typedef vector<Property *> Properties;
class Object {
public:
Object(const InterrogateType &itype);
@ -133,6 +145,7 @@ public:
Functions _constructors;
Functions _methods;
MakeSeqs _make_seqs;
Properties _properties;
enum ProtocolTypes {
PT_sequence = 0x0001,

View File

@ -53,9 +53,9 @@ InterfaceMakerC::
////////////////////////////////////////////////////////////////////
void InterfaceMakerC::
write_prototypes(ostream &out,ostream *out_h) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_prototype_for(out, func);
}
@ -72,9 +72,9 @@ write_prototypes(ostream &out,ostream *out_h) {
////////////////////////////////////////////////////////////////////
void InterfaceMakerC::
write_functions(ostream &out) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_function_for(out, func);
}

View File

@ -817,9 +817,9 @@ write_functions(ostream &out) {
out << "//********************************************************************\n";
out << "//*** Functions for .. Global\n" ;
out << "//********************************************************************\n";
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
if (!func->_itype.is_global() && is_function_legal(func)) {
write_function_for_top(out, NULL, func);
}
@ -876,6 +876,23 @@ write_class_details(ostream &out, Object *obj) {
}
}
Properties::const_iterator pit;
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
Property *property = (*pit);
const InterrogateElement &ielem = property->_ielement;
bool coercion_attempted = false;
if (property->_getter != NULL) {
std::string fname = "PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *)";
write_function_for_name(out, obj, property->_getter, fname, true, coercion_attempted, AT_no_args, false, false);
}
if (property->_setter != NULL) {
std::string fname = "int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *)";
write_function_for_name(out, obj, property->_setter, fname, true, coercion_attempted, AT_single_arg, true, false);
}
}
if (obj->_constructors.size() == 0) {
out << "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds) {\n"
<< " PyErr_SetString(PyExc_TypeError, \"cannot init constant class (" << cClassName << ")\");\n"
@ -893,7 +910,7 @@ write_class_details(ostream &out, Object *obj) {
Function *func = (*fi);
std::string fname = "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)";
write_function_for_name(out, obj, func, fname, true, coercion_attempted, AT_keyword_args, true);
write_function_for_name(out, obj, func, fname, true, coercion_attempted, AT_keyword_args, true, false);
}
if (coercion_attempted) {
// If a coercion attempt was written into the above constructor,
@ -903,7 +920,7 @@ write_class_details(ostream &out, Object *obj) {
Function *func = (*fi);
std::string fname = "int Dtool_InitNoCoerce_" + ClassName + "(PyObject *self, PyObject *args)";
write_function_for_name(out, obj, func, fname, false, coercion_attempted, AT_varargs, true);
write_function_for_name(out, obj, func, fname, false, coercion_attempted, AT_varargs, true, false);
}
} else {
// Otherwise, since the above constructor didn't involve any
@ -1114,9 +1131,9 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
bool force_base_functions = true;
out << "static PyMethodDef python_simple_funcs[] = {\n";
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
if (!func->_itype.is_global() && is_function_legal(func)) {
string name1 = methodNameFromCppName(func, "", false);
string name2 = methodNameFromCppName(func, "", true);
@ -2078,6 +2095,44 @@ write_module_class(ostream &out, Object *obj) {
out << "}\n\n";
}
if (obj->_properties.size() > 0) {
// Write out the array of properties, telling Python which getter and setter
// to call when they are assigned or queried in Python code.
out << "PyGetSetDef Dtool_Properties_" << ClassName << "[] = {\n";
Properties::const_iterator pit;
for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
Property *property = (*pit);
const InterrogateElement &ielem = property->_ielement;
if (property->_getter == NULL || !is_function_legal(property->_getter)) {
continue;
}
out << " {(char *)\"" << ielem.get_name() << "\","
<< " &Dtool_" << ClassName << "_" << ielem.get_name() << "_Getter,";
if (property->_setter == NULL || !is_function_legal(property->_setter)) {
out << " NULL,";
} else {
out << " &Dtool_" << ClassName << "_" << ielem.get_name() << "_Setter,";
}
if (ielem.has_comment()) {
out << "(char *)\n";
output_quoted(out, 4, ielem.get_comment());
out << ",\n ";
} else {
out << " NULL, ";
}
// Extra void* argument; we don't make use of it.
out << "NULL},\n";
}
out << " {NULL},\n";
out << "};\n\n";
}
out << "void Dtool_PyModuleClassInit_" << ClassName << "(PyObject *module) {\n";
out << " static bool initdone = false;\n";
out << " if (!initdone) {\n";
@ -2190,6 +2245,11 @@ write_module_class(ostream &out, Object *obj) {
out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_str = &Dtool_Repr_" << ClassName << ";\n";
}
if (obj->_properties.size() > 0) {
// GetSet descriptor slots.
out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_getset = Dtool_Properties_" << ClassName << ";\n";
}
int num_nested = obj->_itype.number_of_nested_types();
for (int ni = 0; ni < num_nested; ni++) {
TypeIndex nested_index = obj->_itype.get_nested_type(ni);
@ -2395,7 +2455,7 @@ write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker
fname += ")";
bool coercion_attempted = false;
write_function_for_name(out, obj, func, fname, true, coercion_attempted, func->_args_type, false);
write_function_for_name(out, obj, func, fname, true, coercion_attempted, func->_args_type, false, true);
}
////////////////////////////////////////////////////////////////////
@ -2407,7 +2467,7 @@ void InterfaceMakerPythonNative::
write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMaker::Function *func,
const std::string &function_name,
bool coercion_allowed, bool &coercion_attempted,
ArgsType args_type, bool return_int) {
ArgsType args_type, bool return_int, bool write_comment) {
ostringstream out;
std::map<int, std::set<FunctionRemap *> > MapSets;
@ -2462,7 +2522,11 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
// Other functions should raise an exception if the this
// pointer isn't set or is the wrong type.
out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n";
out << " return NULL;\n";
if (return_int) {
out << " return -1;\n";
} else {
out << " return NULL;\n";
}
}
out << " }\n";
}
@ -2639,7 +2703,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak
FunctionComment = FunctionComment1 + "\n" + FunctionComment;
}
if (!return_int) {
if (write_comment) {
// Write out the function doc string. We only do this if it is
// not a constructor, since we don't have a place to put the
// constructor doc string.
@ -4004,13 +4068,30 @@ record_object(TypeIndex type_index) {
for (int ei = 0; ei < num_elements; ei++) {
ElementIndex element_index = itype.get_element(ei);
const InterrogateElement &ielement = idb->get_element(element_index);
if (ielement.has_getter()) {
FunctionIndex func_index = ielement.get_getter();
record_function(itype, func_index);
}
Property *property = new Property(ielement);
if (ielement.has_setter()) {
FunctionIndex func_index = ielement.get_setter();
record_function(itype, func_index);
Function *setter = record_function(itype, func_index);
if (is_function_legal(setter)) {
property->_setter = setter;
}
}
if (ielement.has_getter()) {
FunctionIndex func_index = ielement.get_getter();
Function *getter = record_function(itype, func_index);
if (is_function_legal(getter)) {
property->_getter = getter;
}
}
if (property->_getter != NULL) {
object->_properties.push_back(property);
} else {
// No use exporting a property without a getter.
delete property;
}
}

View File

@ -95,7 +95,7 @@ private:
void write_function_for_name(ostream &out, Object *obj, Function *func,
const std::string &name,
bool coercion_allowed, bool &coercion_attempted,
ArgsType args_type, bool return_int);
ArgsType args_type, bool return_int, bool write_comment);
void write_function_forset(ostream &out, Object *obj, Function *func,
std::set<FunctionRemap*> &remaps, string &expected_params,

View File

@ -55,9 +55,9 @@ InterfaceMakerPythonObj::
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonObj::
write_prototypes(ostream &out, ostream *out_h) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_prototype_for(out, func);
}
@ -74,9 +74,9 @@ write_prototypes(ostream &out, ostream *out_h) {
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonObj::
write_functions(ostream &out) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_function_for(out, func);
}

View File

@ -53,9 +53,9 @@ InterfaceMakerPythonSimple::
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonSimple::
write_prototypes(ostream &out,ostream *out_h) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_prototype_for(out, func);
}
@ -72,9 +72,9 @@ write_prototypes(ostream &out,ostream *out_h) {
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonSimple::
write_functions(ostream &out) {
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
write_function_for(out, func);
}
@ -93,9 +93,9 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
out << "static PyMethodDef python_simple_funcs[] = {\n";
Functions::iterator fi;
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
Function *func = (*fi).second;
Function::Remaps::const_iterator ri;
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
FunctionRemap *remap = (*ri);

View File

@ -44,6 +44,7 @@
#include "cppTypeDeclaration.h"
#include "cppEnumType.h"
#include "cppCommentBlock.h"
#include "cppMakeProperty.h"
#include "cppMakeSeq.h"
#include "pnotify.h"
@ -1357,7 +1358,7 @@ scan_element(CPPInstance *element, CPPStructType *struct_type,
ielement._name = element->get_local_name(scope);
ielement._scoped_name = descope(element->get_local_name(&parser));
// See if there happens to be a comment before the element.
// See if there happens to be a comment before the MAKE_PROPERTY macro.
if (element->_leading_comment != (CPPCommentBlock *)NULL) {
ielement._comment = trim_blanks(element->_leading_comment->_comment);
}
@ -1774,6 +1775,90 @@ get_function(CPPInstance *function, string description,
return index;
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::get_make_property
// Access: Private
// Description: Adds the indicated make_property to the database,
// if it is not already present. In either case,
// returns the MakeSeqIndex of the make_seq within the
// database.
////////////////////////////////////////////////////////////////////
ElementIndex InterrogateBuilder::
get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type) {
string property_name = make_property->get_local_name(&parser);
// First, check to see if it's already there.
PropertiesByName::const_iterator tni =
_properties_by_name.find(property_name);
if (tni != _properties_by_name.end()) {
ElementIndex index = (*tni).second;
return index;
}
// Find the getter so we can get its return type.
CPPInstance *getter = NULL;
CPPType *return_type = NULL;
CPPFunctionGroup *fgroup = make_property->_getter;
CPPFunctionGroup::Instances::const_iterator fi;
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
CPPInstance *function = (*fi);
CPPFunctionType *ftype =
function->_type->as_function_type();
if (ftype != NULL && ftype->_parameters->_parameters.size() == 0) {
getter = function;
return_type = ftype->_return_type;
// The return type of the non-const method probably better represents
// the type of the property we are creating.
if ((ftype->_flags & CPPFunctionType::F_const_method) == 0) {
break;
}
}
}
if (getter == NULL || return_type == NULL) {
cerr << "No instance of getter '"
<< make_property->_getter->_name << "' is suitable!\n";
return 0;
}
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
// It isn't here, so we'll have to define it.
ElementIndex index = idb->get_next_index();
_properties_by_name[property_name] = index;
InterrogateElement iproperty;
iproperty._name = make_property->get_simple_name();
iproperty._scoped_name = descope(make_property->get_local_name(&parser));
iproperty._type = get_type(return_type, false);
iproperty._flags |= InterrogateElement::F_has_getter;
iproperty._getter = get_function(getter, "", struct_type,
struct_type->get_scope(), 0);
// See if there happens to be a comment before the element.
if (make_property->_leading_comment != (CPPCommentBlock *)NULL) {
iproperty._comment = trim_blanks(make_property->_leading_comment->_comment);
}
// Now look for setters.
fgroup = make_property->_setter;
if (fgroup != NULL) {
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
CPPInstance *function = (*fi);
iproperty._flags |= InterrogateElement::F_has_setter;
iproperty._setter = get_function(function, "", struct_type,
struct_type->get_scope(), 0);
}
}
idb->add_element(index, iproperty);
return index;
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::get_make_seq
// Access: Private
@ -2285,6 +2370,10 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
TypeIndex nested_index = get_type(type, false);
itype._nested_types.push_back(nested_index);
}
} else if ((*di)->get_subtype() == CPPDeclaration::ST_make_property) {
ElementIndex element_index = get_make_property((*di)->as_make_property(), cpptype);
itype._elements.push_back(element_index);
}
}

View File

@ -38,6 +38,7 @@ class CPPScope;
class CPPIdentifier;
class CPPNameComponent;
class CPPManifest;
class CPPMakeProperty;
class CPPMakeSeq;
class InterrogateType;
class InterrogateFunction;
@ -108,6 +109,9 @@ public:
CPPStructType *struct_type, CPPScope *scope,
int flags, const string &expression = string());
ElementIndex
get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type);
MakeSeqIndex
get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type);
@ -132,10 +136,12 @@ public:
typedef map<string, TypeIndex> TypesByName;
typedef map<string, FunctionIndex> FunctionsByName;
typedef map<string, MakeSeqIndex> MakeSeqsByName;
typedef map<string, ElementIndex> PropertiesByName;
TypesByName _types_by_name;
FunctionsByName _functions_by_name;
MakeSeqsByName _make_seqs_by_name;
PropertiesByName _properties_by_name;
typedef map<string, char> IncludeFiles;
IncludeFiles _include_files;

View File

@ -73,11 +73,11 @@ PUBLISHED:
virtual void transform(const LMatrix4d &mat);
public:
double _switch_in, _switch_out, _fade;
LPoint3d _center;
public:
static TypeHandle get_class_type() {
return _type_handle;
}