remove dead code

This commit is contained in:
David Rose
2001-10-02 23:24:19 +00:00
parent 3fccb0f373
commit 8196afae9f
20 changed files with 19 additions and 2702 deletions

View File

@@ -5,11 +5,8 @@
#begin bin_target
#define TARGET interrogate
// While I'm working on this, I'll temporarily take out the composite
// build.
// #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define SOURCES \
classBuilder.h classBuilderPythonObj.h \
functionRemap.h \
functionWriter.h \
functionWriterPtrFromPython.h functionWriterPtrToPython.h \
@@ -28,12 +25,9 @@
parameterRemapReferenceToConcrete.h \
parameterRemapReferenceToPointer.h parameterRemapThis.h \
parameterRemapToString.h parameterRemapUnchanged.h \
typeManager.h wrapperBuilder.h wrapperBuilderC.h \
wrapperBuilderPython.h wrapperBuilderPythonObj.h
typeManager.h
// #define INCLUDED_SOURCES \
#define SOURCES $[SOURCES] \
classBuilder.cxx classBuilderPythonObj.cxx \
#define INCLUDED_SOURCES \
functionRemap.cxx \
functionWriter.cxx \
functionWriterPtrFromPython.cxx functionWriterPtrToPython.cxx \
@@ -52,8 +46,7 @@
parameterRemapReferenceToConcrete.cxx \
parameterRemapReferenceToPointer.cxx parameterRemapThis.cxx \
parameterRemapToString.cxx parameterRemapUnchanged.cxx \
typeManager.cxx wrapperBuilder.cxx wrapperBuilderC.cxx \
wrapperBuilderPython.cxx wrapperBuilderPythonObj.cxx
typeManager.cxx
#end bin_target

View File

@@ -1,55 +0,0 @@
// Filename: classBuilder.cxx
// Created by: drose (17Sep01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "classBuilder.h"
#include "interrogate.h"
////////////////////////////////////////////////////////////////////
// Function: ClassBuilder::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
ClassBuilder::
ClassBuilder() {
_struct_type = (CPPStructType *)NULL;
_type_index = -1;
}
////////////////////////////////////////////////////////////////////
// Function: ClassBuilder::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
ClassBuilder::
~ClassBuilder() {
}
////////////////////////////////////////////////////////////////////
// Function: ClassBuilder::set_class
// Access: Public, Virtual
// Description: Sets the class that will be generated by this
// ClassBuilder. Returns true on success, false if the
// class cannot be output for some reason.
////////////////////////////////////////////////////////////////////
bool ClassBuilder::
set_class(TypeIndex type_index, CPPStructType *struct_type) {
_type_index = type_index;
_struct_type = struct_type;
return true;
}

View File

@@ -1,58 +0,0 @@
// Filename: classBuilder.h
// Created by: drose (17Sep01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef CLASSBUILDER_H
#define CLASSBUILDER_H
#include "dtoolbase.h"
#include "interrogate_interface.h"
class CPPScope;
class CPPStructType;
class InterrogateType;
////////////////////////////////////////////////////////////////////
// Class : ClassBuilder
// Description : Similar to WrapperBuilder, this contains all the
// information needed to generate whatever source code
// might be associated with a complete class definition
// (as opposed to the source code associated with each
// function).
//
// This is an abstract class, and is implemented
// separately for each kind of generated output. Most
// kinds do not need to write anything special for the
// class definition, so do not implement this class. At
// the present, only ClassBuilderPythonObj is necessary.
////////////////////////////////////////////////////////////////////
class ClassBuilder {
public:
ClassBuilder();
virtual ~ClassBuilder();
virtual bool set_class(TypeIndex type_index, CPPStructType *struct_type);
virtual void write_prototype(ostream &out) const=0;
virtual void write_code(ostream &out) const=0;
protected:
CPPStructType *_struct_type;
TypeIndex _type_index;
};
#endif

View File

@@ -1,104 +0,0 @@
// Filename: classBuilderPythonObj.cxx
// Created by: drose (17Sep01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "classBuilderPythonObj.h"
#include "cppStructType.h"
#include "interrogateBuilder.h"
#include "interrogate.h"
#include "interrogateType.h"
#include "interrogateDatabase.h"
////////////////////////////////////////////////////////////////////
// Function: ClassBuilderPythonObj::set_class
// Access: Public, Virtual
// Description: Sets the class that will be generated by this
// ClassBuilder. Returns true on success, false if the
// class cannot be output for some reason.
////////////////////////////////////////////////////////////////////
bool ClassBuilderPythonObj::
set_class(TypeIndex type_index, CPPStructType *struct_type) {
if (!ClassBuilder::set_class(type_index, struct_type)) {
return false;
}
_name = get_builder_name(_struct_type);
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
const InterrogateType &itype = idb->get_type(_type_index);
int num_methods = itype.number_of_methods();
cerr << " // index = " << _type_index << " methods = " << num_methods
<< " type = " << itype.get_name() << "\n";
for (int i = 0; i < num_methods; i++) {
FunctionIndex fi = itype.get_method(i);
const InterrogateFunction &func = idb->get_function(fi);
cerr << " // " << func.get_name() << "\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ClassBuilderPythonObj::write_prototype
// Access: Public, Virtual
// Description: Generates prototypes for whatever functions will be
// generated by write_code().
////////////////////////////////////////////////////////////////////
void ClassBuilderPythonObj::
write_prototype(ostream &out) const {
out << "PyObject *" << _name << "();\n";
}
////////////////////////////////////////////////////////////////////
// Function: ClassBuilderPythonObj::write_code
// Access: Public, Virtual
// Description: Generates whatever code is appropriate for this
// class.
////////////////////////////////////////////////////////////////////
void ClassBuilderPythonObj::
write_code(ostream &out) const {
out << "PyObject *\n"
<< _name << "() {\n"
<< " static PyObject *wrapper = (PyObject *)NULL;\n"
<< " static PyMethodDef methods[] = {\n";
out << " };\n"
<< " if (wrapper == (PyObject *)NULL) {\n"
<< " PyObject *bases = PyTuple_New(0);\n"
<< " PyObject *dict = PyDict_New();\n"
<< " PyObject *name = PyString_FromString(\""
<< InterrogateBuilder::clean_identifier(_struct_type->get_simple_name())
<< "\");\n"
<< " wrapper = PyClass_New(bases, dict, name);\n"
<< " }\n"
<< " return wrapper;\n"
<< "}\n\n";
}
////////////////////////////////////////////////////////////////////
// Function: ClassBuilderPythonObj::get_builder_name
// Access: Public, Static
// Description: Returns the name of the ClassBuilder function
// generated for the indicated struct type.
////////////////////////////////////////////////////////////////////
string ClassBuilderPythonObj::
get_builder_name(CPPType *struct_type) {
return "get_python_class_" +
InterrogateBuilder::clean_identifier(struct_type->get_local_name(&parser));
}

View File

@@ -1,45 +0,0 @@
// Filename: classBuilderPythonObj.h
// Created by: drose (17Sep01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef CLASSBUILDERPYTHONOBJ_H
#define CLASSBUILDERPYTHONOBJ_H
#include "dtoolbase.h"
#include "classBuilder.h"
class CPPType;
////////////////////////////////////////////////////////////////////
// Class : ClassBuilderPythonObj
// Description : A specialization on ClassBuilder that builds
// actual Python class objects.
////////////////////////////////////////////////////////////////////
class ClassBuilderPythonObj : public ClassBuilder {
public:
virtual bool set_class(TypeIndex type_index, CPPStructType *struct_type);
virtual void write_prototype(ostream &out) const;
virtual void write_code(ostream &out) const;
static string get_builder_name(CPPType *struct_type);
private:
string _name;
};
#endif

View File

@@ -24,10 +24,9 @@
////////////////////////////////////////////////////////////////////
// Class : FunctionWriter
// Description : This is an abstract class that can be used by the
// various WrapperBuilders to indicate a static helper
// various InterfaceMakers to indicate a generic helper
// function or variable that needs to be written to the
// generated source file before the code for the
// WrapperBuilders.
// generated source file.
////////////////////////////////////////////////////////////////////
class FunctionWriter {
public:

View File

@@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////////////
// Class : FunctionWriters
// Description : A set of zero or more FunctionWriter pointers
// accumulated by the various WrapperBuilder objects
// accumulated by the various InterfaceMaker objects
// that are generating code for one particular output
// source file.
////////////////////////////////////////////////////////////////////

View File

@@ -18,12 +18,6 @@
#include "interrogateBuilder.h"
#include "interrogate.h"
#include "wrapperBuilder.h"
#include "wrapperBuilderC.h"
#include "wrapperBuilderPython.h"
#include "wrapperBuilderPythonObj.h"
#include "classBuilder.h"
#include "classBuilderPythonObj.h"
#include "parameterRemap.h"
#include "typeManager.h"
#include "functionWriters.h"
@@ -1603,248 +1597,6 @@ get_function(CPPInstance *function, string description,
return index;
}
// ////////////////////////////////////////////////////////////////////
// // Function: InterrogateBuilder::get_wrapper_builder_c
// // Access: Private
// // Description: Returns a WrapperBuilder object suitable for wrapping
// // the indicated function. This may either be a
// // newly-allocated object, or a previously-allocated one
// // if function overloading of multiple functions is to
// // be implemented within the WrapperBuilder.
// ////////////////////////////////////////////////////////////////////
// WrapperBuilder *InterrogateBuilder::
// get_wrapper_builder_c(const InterrogateFunction &) {
// return new WrapperBuilderC;
// }
// ////////////////////////////////////////////////////////////////////
// // Function: InterrogateBuilder::get_wrapper_builder_python
// // Access: Private
// // Description: Returns a WrapperBuilder object suitable for wrapping
// // the indicated function. This may either be a
// // newly-allocated object, or a previously-allocated one
// // if function overloading of multiple functions is to
// // be implemented within the WrapperBuilder.
// ////////////////////////////////////////////////////////////////////
// WrapperBuilder *InterrogateBuilder::
// get_wrapper_builder_python(const InterrogateFunction &) {
// return new WrapperBuilderPython;
// }
// ////////////////////////////////////////////////////////////////////
// // Function: InterrogateBuilder::get_wrapper_builder_python_obj
// // Access: Private
// // Description: Returns a WrapperBuilder object suitable for wrapping
// // the indicated function. This may either be a
// // newly-allocated object, or a previously-allocated one
// // if function overloading of multiple functions is to
// // be implemented within the WrapperBuilder.
// ////////////////////////////////////////////////////////////////////
// WrapperBuilder *InterrogateBuilder::
// get_wrapper_builder_python_obj(const InterrogateFunction &ifunction) {
// string scoped_name = ifunction.get_scoped_name();
// OverloadedWrappers::iterator wi;
// wi = _python_obj_wrappers.find(scoped_name);
// if (wi == _python_obj_wrappers.end()) {
// wi = _python_obj_wrappers.insert(OverloadedWrappers::value_type(scoped_name, new WrapperBuilderPythonObj)).first;
// }
// return (*wi).second;
// }
// ////////////////////////////////////////////////////////////////////
// // Function: InterrogateBuilder::make_wrappers
// // Access: Private
// // Description: Makes the wrappers for all of the newly-defined
// // functions. This might result in the definition of a
// // few new incidental types necessary to support the
// // wrappers' parameters.
// ////////////////////////////////////////////////////////////////////
// void InterrogateBuilder::
// make_wrappers() {
// while (!_new_functions.empty()) {
// // Make a copy of the new_functions list, and iterate through the
// // copy. This is just in case we end up defining a few *more*
// // functions while we do this.
// NewFunctions new_functions;
// new_functions.swap(_new_functions);
// NewFunctions::iterator ni;
// for (ni = new_functions.begin(); ni != new_functions.end(); ++ni) {
// const NewFunction &nf = (*ni);
// int num_default_parameters = nf._ftype->get_num_default_parameters();
// InterrogateFunction &ifunction =
// InterrogateDatabase::get_ptr()->update_function(nf._function_index);
// if (build_c_wrappers) {
// // Make the C wrapper(s).
// for (int dp = 0; dp <= num_default_parameters; dp++) {
// FunctionWrapperIndex wrapper =
// get_wrapper(nf._function_index, get_wrapper_builder_c(ifunction),
// nf._function, nf._description,
// nf._struct_type, nf._scope,
// nf._wtype, nf._expression, dp);
// if (wrapper != 0) {
// ifunction._c_wrappers.push_back(wrapper);
// }
// }
// }
// if (build_python_wrappers) {
// // Make the Python C-style function wrapper.
// for (int dp = 0; dp <= num_default_parameters; dp++) {
// FunctionWrapperIndex wrapper =
// get_wrapper(nf._function_index, get_wrapper_builder_python(ifunction),
// nf._function, nf._description,
// nf._struct_type, nf._scope,
// nf._wtype, nf._expression, dp);
// if (wrapper != 0) {
// ifunction._python_wrappers.push_back(wrapper);
// }
// }
// }
// if (build_python_obj_wrappers) {
// // Make the Python C++-style method wrapper. This style
// // wrapper does not need to be recorded in the database,
// // because it can be executed directly by Python.
// WrapperBuilder *wbuilder = get_wrapper_builder_python_obj(ifunction);
// for (int dp = num_default_parameters; dp >= 0; dp--) {
// get_wrapper(nf._function_index, wbuilder,
// nf._function, nf._description,
// nf._struct_type, nf._scope,
// nf._wtype, nf._expression, dp);
// }
// }
// }
// }
// }
// ////////////////////////////////////////////////////////////////////
// // Function: InterrogateBuilder::get_wrapper
// // Access: Private
// // Description: Defines a particular wrapper for the given function.
// // wbuilder is a newly-allocated WrapperBuilder of the
// // appropriate type.
// ////////////////////////////////////////////////////////////////////
// FunctionWrapperIndex InterrogateBuilder::
// get_wrapper(FunctionIndex function_index, WrapperBuilder *wbuilder,
// CPPInstance *function, string description,
// CPPStructType *struct_type,
// CPPScope *scope, WrapperBuilder::Type wtype,
// const string &expression,
// int num_default_parameters) {
// string function_signature =
// TypeManager::get_function_signature(function, num_default_parameters);
// if (description.empty()) {
// // Make up a description string if we weren't given one.
// ostringstream desc;
// function->output(desc, 0, &parser, false, num_default_parameters);
// desc << ";";
// description = desc.str();
// }
// int def_index =
// wbuilder->add_function(function, description, struct_type, scope,
// function_signature, wtype,
// expression, num_default_parameters);
// if (def_index < 0) {
// // This function can't be exported for some reason.
// // We can't safely delete this, because it might be shared.
// // delete wbuilder;
// return 0;
// }
// assert(def_index >= 0 && def_index < (int)wbuilder->_def.size());
// WrapperBuilder::FunctionDef *def = wbuilder->_def[def_index];
// if (def_index == 0) {
// // If this is the first definition for this particular wrapper,
// // assign a new wrapper index and hash number.
// FunctionWrapperIndex index =
// InterrogateDatabase::get_ptr()->get_next_index();
// wbuilder->_wrapper_index = index;
// hash_function_signature(wbuilder);
// }
// InterrogateFunctionWrapper iwrapper;
// iwrapper._function = function_index;
// // We do assume that two different libraries will not hash to the
// // same name. This is pretty unlikely, although there could be big
// // problems if it ever happens. If it does, we'll probably need to
// // add an interface so the user can specify a hash offset on a
// // per-library basis or something like that.
// iwrapper._unique_name = _library_hash_name + wbuilder->_hash;
// WrapperBuilder::Parameters::const_iterator pi;
// for (pi = def->_parameters.begin();
// pi != def->_parameters.end();
// ++pi) {
// InterrogateFunctionWrapper::Parameter param;
// param._parameter_flags = 0;
// if ((*pi)._remap->new_type_is_atomic_string()) {
// param._type = get_atomic_string_type();
// } else {
// param._type = get_type((*pi)._remap->get_new_type(), false);
// }
// param._name = (*pi)._name;
// if ((*pi)._has_name) {
// param._parameter_flags |= InterrogateFunctionWrapper::PF_has_name;
// }
// iwrapper._parameters.push_back(param);
// }
// if (def->_has_this) {
// // If one of the parameters is "this", it must be the first one.
// assert(!iwrapper._parameters.empty());
// iwrapper._parameters.front()._parameter_flags |=
// InterrogateFunctionWrapper::PF_is_this;
// }
// if (def->_return_type->new_type_is_atomic_string()) {
// iwrapper._return_type = get_atomic_string_type();
// } else {
// iwrapper._return_type =
// get_type(def->_return_type->get_new_type(), false);
// }
// if (!def->_void_return) {
// iwrapper._flags |= InterrogateFunctionWrapper::F_has_return;
// if (def->_return_value_needs_management) {
// iwrapper._flags |= InterrogateFunctionWrapper::F_caller_manages;
// int destructor = def->_return_value_destructor;
// if (destructor != 0) {
// iwrapper._return_value_destructor = destructor;
// } else {
// // We don't need to report this warning, since the FFI code
// // understands that if the destructor function is zero, it
// // should use the regular class destructor.
// // nout << "Warning! Destructor for "
// // << *def->_return_type->get_orig_type()
// // << " is unavailable.\n"
// // << " Cannot manage return value for:\n "
// // << description << "\n";
// }
// }
// }
// if (def_index == 0) {
// InterrogateDatabase::get_ptr()->add_wrapper(wbuilder->_wrapper_index, iwrapper);
// }
// return wbuilder->_wrapper_index;
// }
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::get_atomic_string_type
// Access: Private
@@ -2299,31 +2051,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
0);
itype._flags |= InterrogateType::F_implicit_destructor;
}
// Finally, generate any ClassBuilder objects appropriate to this
// type.
// make_class_builders(type_index, cpptype);
}
/*
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::make_class_builders
// Access: Private
// Description: Creates whatever ClassBuilder objects might be
// required for the indicated class type and stores them
// in the InterrogateBuilder object for later generation
// of code.
////////////////////////////////////////////////////////////////////
void InterrogateBuilder::
make_class_builders(TypeIndex type_index, CPPStructType *cpptype) {
if (build_python_obj_wrappers) {
ClassBuilder *cbuilder = new ClassBuilderPythonObj;
cbuilder->set_class(type_index, cpptype);
_class_builders.push_back(cbuilder);
}
}
*/
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::update_method_comment
// Access: Private

View File

@@ -23,7 +23,6 @@
#include "interrogate_interface.h"
#include "interrogate_request.h"
#include "wrapperBuilder.h"
#include <map>
#include <set>
@@ -45,7 +44,6 @@ class CPPNameComponent;
class CPPManifest;
class InterrogateType;
class InterrogateFunction;
class ClassBuilder;
class FunctionRemap;
class InterfaceMaker;
@@ -109,20 +107,6 @@ private:
CPPStructType *struct_type, CPPScope *scope,
int flags, const string &expression = string());
/*
WrapperBuilder *get_wrapper_builder_c(const InterrogateFunction &ifunction);
WrapperBuilder *get_wrapper_builder_python(const InterrogateFunction &ifunction);
WrapperBuilder *get_wrapper_builder_python_obj(const InterrogateFunction &ifunction);
void make_wrappers();
FunctionWrapperIndex
get_wrapper(FunctionIndex function_index,
WrapperBuilder *wbuilder, CPPInstance *function,
string description, CPPStructType *struct_type, CPPScope *scope,
WrapperBuilder::Type wtype, const string &expression,
int num_default_parameters);
*/
TypeIndex get_atomic_string_type();
TypeIndex get_type(CPPType *type, bool global);
@@ -131,7 +115,6 @@ private:
void define_wrapped_type(InterrogateType &itype, CPPConstType *cpptype);
void define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
TypeIndex type_index, bool forced);
void make_class_builders(TypeIndex type_index, CPPStructType *cpptype);
void update_method_comment(CPPInstance *function, CPPStructType *struct_type,
CPPScope *scope);
void define_method(CPPFunctionGroup *fgroup, InterrogateType &itype,
@@ -144,31 +127,12 @@ private:
static string trim_blanks(const string &str);
/*
class NewFunction {
public:
CPPInstance *_function;
string _description;
CPPFunctionType *_ftype;
CPPStructType *_struct_type;
CPPScope *_scope;
WrapperBuilder::Type _wtype;
string _expression;
int _function_index;
};
typedef vector<NewFunction> NewFunctions;
NewFunctions _new_functions;
*/
typedef map<string, TypeIndex> TypesByName;
typedef map<string, FunctionIndex> FunctionsByName;
TypesByName _types_by_name;
FunctionsByName _functions_by_name;
typedef vector<ClassBuilder *> ClassBuilders;
ClassBuilders _class_builders;
typedef map<string, char> IncludeFiles;
IncludeFiles _include_files;
@@ -182,9 +146,6 @@ private:
string _library_hash_name;
typedef map<string, WrapperBuilder *> OverloadedWrappers;
OverloadedWrappers _python_obj_wrappers;
friend class FunctionRemap;
};

View File

@@ -1,3 +1,13 @@
#include "interrogateBuilder.cxx"
#include "functionRemap.cxx"
#include "functionWriter.cxx"
#include "functionWriterPtrFromPython.cxx"
#include "functionWriterPtrToPython.cxx"
#include "functionWriters.cxx"
#include "interfaceMaker.cxx"
#include "interfaceMakerC.cxx"
#include "interfaceMakerPython.cxx"
#include "interfaceMakerPythonObj.cxx"
#include "interfaceMakerPythonSimple.cxx"

View File

@@ -1,9 +1,6 @@
#include "interrogate.cxx"
#include "typeManager.cxx"
#include "wrapperBuilder.cxx"
#include "wrapperBuilderC.cxx"
#include "wrapperBuilderPython.cxx"
#include "parameterRemap.cxx"
#include "parameterRemapBasicStringRefToString.cxx"
#include "parameterRemapBasicStringToString.cxx"

View File

@@ -17,7 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "parameterRemapBasicStringToString.h"
#include "wrapperBuilder.h"
#include "interfaceMaker.h"
////////////////////////////////////////////////////////////////////
// Function: ParameterRemapBasicStringToString::Constructor
@@ -53,7 +53,7 @@ pass_parameter(ostream &out, const string &variable_name) {
////////////////////////////////////////////////////////////////////
string ParameterRemapBasicStringToString::
prepare_return_expr(ostream &out, int indent_level, const string &expression) {
WrapperBuilder::indent(out, indent_level)
InterfaceMaker::indent(out, indent_level)
<< "static basic_string<char> string_holder = " << expression << ";\n";
return "string_holder";
}

View File

@@ -1,817 +0,0 @@
// Filename: wrapperBuilder.cxx
// Created by: drose (01Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "wrapperBuilder.h"
#include "interrogate.h"
#include "parameterRemap.h"
#include "parameterRemapThis.h"
#include "parameterRemapUnchanged.h"
#include "parameterRemapReferenceToPointer.h"
#include "parameterRemapConcreteToPointer.h"
#include "parameterRemapEnumToInt.h"
#include "parameterRemapConstToNonConst.h"
#include "parameterRemapReferenceToConcrete.h"
#include "parameterRemapCharStarToString.h"
#include "parameterRemapBasicStringToString.h"
#include "parameterRemapBasicStringRefToString.h"
#include "parameterRemapPTToPointer.h"
#include "interrogateBuilder.h"
#include "typeManager.h"
#include <interrogateDatabase.h>
#include <cppInstance.h>
#include <cppFunctionType.h>
#include <cppParameterList.h>
#include <cppStructType.h>
#include <cppReferenceType.h>
#include <notify.h>
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::FunctionDef::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
WrapperBuilder::FunctionDef::
FunctionDef() {
_return_type = (ParameterRemap *)NULL;
_void_return = true;
_has_this = false;
_is_method = false;
_type = T_normal;
_function = (CPPInstance *)NULL;
_struct_type = (CPPStructType *)NULL;
_scope = (CPPScope *)NULL;
_ftype = (CPPFunctionType *)NULL;
_num_default_parameters = 0;
_return_value_needs_management = false;
_return_value_destructor = 0;
_manage_reference_count = false;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::FunctionDef::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
WrapperBuilder::FunctionDef::
~FunctionDef() {
Parameters::iterator pi;
for (pi = _parameters.begin(); pi != _parameters.end(); ++pi) {
delete (*pi)._remap;
}
_parameters.clear();
if (_return_type != (ParameterRemap *)NULL) {
delete _return_type;
_return_type = (ParameterRemap *)NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::FunctionDef::Copy constructor
// Access: Private
// Description: These are not designed to be copied.
////////////////////////////////////////////////////////////////////
WrapperBuilder::FunctionDef::
FunctionDef(const FunctionDef &) {
assert(false);
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::FunctionDef::Copy assignment operator
// Access: Private
// Description: These are not designed to be copied.
////////////////////////////////////////////////////////////////////
void WrapperBuilder::FunctionDef::
operator = (const FunctionDef &) {
assert(false);
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
WrapperBuilder::
WrapperBuilder() {
_wrapper_index = 0;
_is_valid = false;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
WrapperBuilder::
~WrapperBuilder() {
Def::iterator di;
for (di = _def.begin(); di != _def.end(); ++di) {
delete (*di);
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::add_function
// Access: Public
// Description: Sets up the builder according to the indicated
// function. The value of num_default_parameters
// represents the number of parameters on the end to
// assign to their default values for this particular
// wrapper.
//
// If this is called only once, then the WrapperBuilder
// will generate a wrapper that only calls the
// particular C++ function. Otherwise, if this is
// called multiple times (and the WrapperBuilder type
// supports this), it will generate a wrapper that can
// handle overloading, and will call the appropriate
// C++ function based on the input parameters.
//
// Returns the definition index if successful, or -1 if
// the function cannot be wrapped for some reason.
////////////////////////////////////////////////////////////////////
int WrapperBuilder::
add_function(CPPInstance *function, const string &description,
CPPStructType *struct_type,
CPPScope *scope, const string &function_signature,
WrapperBuilder::Type type,
const string &expression,
int num_default_parameters) {
_is_valid = true;
int def_index = (int)_def.size();
FunctionDef *def = new FunctionDef;
_def.push_back(def);
def->_function = function;
def->_description = description;
def->_struct_type = struct_type;
def->_scope = scope;
def->_function_signature = function_signature;
def->_expression = expression;
def->_num_default_parameters = num_default_parameters;
def->_parameters.clear();
def->_ftype = def->_function->_type->resolve_type(scope, &parser)->as_function_type();
assert(def->_ftype != (CPPFunctionType *)NULL);
def->_has_this = false;
def->_is_method = false;
def->_type = type;
if ((def->_ftype->_flags & CPPFunctionType::F_constructor) != 0) {
def->_type = T_constructor;
} else if ((def->_ftype->_flags & CPPFunctionType::F_destructor) != 0) {
def->_type = T_destructor;
} else if ((def->_ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) {
def->_type = T_typecast_method;
}
if (def->_struct_type != (CPPStructType *)NULL &&
((function->_storage_class & CPPInstance::SC_static) == 0) &&
def->_type != T_constructor) {
// If this is a method, but not a static method, and not a
// constructor, then we may need to synthesize a "this" parameter.
def->_is_method = true;
if (synthesize_this_parameter()) {
Parameter param;
param._name = "this";
param._has_name = true;
bool is_const = (def->_ftype->_flags & CPPFunctionType::F_const_method) != 0;
param._remap = new ParameterRemapThis(def->_struct_type, is_const);
def->_parameters.push_back(param);
def->_has_this = true;
}
// Also check the name of the function. If it's one of the
// assignment-style operators, flag it as such.
string fname = def->_function->get_simple_name();
if (fname == "operator =" ||
fname == "operator *=" ||
fname == "operator /=" ||
fname == "operator %=" ||
fname == "operator +=" ||
fname == "operator -=" ||
fname == "operator |=" ||
fname == "operator &=" ||
fname == "operator ^=" ||
fname == "operator <<=" ||
fname == "operator >>=") {
def->_type = T_assignment_method;
}
}
const CPPParameterList::Parameters &params =
def->_ftype->_parameters->_parameters;
for (int i = 0; i < (int)params.size() - num_default_parameters; i++) {
CPPType *type = params[i]->_type->resolve_type(&parser, def->_scope);
Parameter param;
param._has_name = true;
param._name = params[i]->get_simple_name();
if (param._name.empty()) {
// If the parameter has no name, record it as being nameless,
// but also synthesize one in case someone asks anyway.
param._has_name = false;
ostringstream param_name;
param_name << "param" << i;
param._name = param_name.str();
}
param._remap = make_remap(def_index, type);
param._remap->set_default_value(params[i]->_initializer);
if (!param._remap->is_valid()) {
_is_valid = false;
}
def->_parameters.push_back(param);
}
if (def->_type == T_constructor) {
// Constructors are a special case. These appear to return void
// as seen by the parser, but we know they actually return a new
// concrete instance.
if (def->_struct_type == (CPPStructType *)NULL) {
nout << "Method " << *def->_function << " has no struct type\n";
_is_valid = false;
} else {
def->_return_type = make_remap(def_index, def->_struct_type);
def->_void_return = false;
}
} else if (def->_type == T_assignment_method) {
// Assignment-type methods are also a special case. We munge
// these to return *this, which is a semi-standard C++ convention
// anyway. We just enforce it.
if (def->_struct_type == (CPPStructType *)NULL) {
nout << "Method " << *def->_function << " has no struct type\n";
_is_valid = false;
} else {
CPPType *ref_type = CPPType::new_type(new CPPReferenceType(def->_struct_type));
def->_return_type = make_remap(def_index, ref_type);
def->_void_return = false;
}
} else {
// The normal case.
CPPType *rtype = def->_ftype->_return_type->resolve_type(&parser, def->_scope);
def->_return_type = make_remap(def_index, rtype);
def->_void_return = TypeManager::is_void(rtype);
}
if (!def->_return_type->is_valid()) {
_is_valid = false;
}
// Do we need to manage the return value?
def->_return_value_needs_management =
def->_return_type->return_value_needs_management();
def->_return_value_destructor =
def->_return_type->get_return_value_destructor();
// Should we manage a reference count?
CPPType *return_type = def->_return_type->get_new_type();
CPPType *return_meat_type = TypeManager::unwrap_pointer(return_type);
if (manage_reference_counts &&
TypeManager::is_reference_count_pointer(return_type) &&
!TypeManager::has_protected_destructor(return_meat_type)) {
// Yes!
def->_manage_reference_count = true;
def->_return_value_needs_management = true;
// This is problematic, because we might not have the class in
// question fully defined here, particularly if the class is
// defined in some other library.
def->_return_value_destructor = builder.get_destructor_for(return_meat_type);
}
if (!_is_valid) {
// Invalid function wrapper. Too bad.
_def.pop_back();
delete def;
return -1;
}
return def_index;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::get_function_writers
// Access: Public, Virtual
// Description: Adds whatever list of FunctionWriters might be needed
// for this particular WrapperBuilder. These will be
// generated to the output source file before
// write_wrapper() is called.
////////////////////////////////////////////////////////////////////
void WrapperBuilder::
get_function_writers(FunctionWriters &) {
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::synthesize_this_parameter
// Access: Public, Virtual
// Description: Returns true if this particular wrapper type requires
// an explicit "this" parameter to be added to the
// function parameter list when appropriate, or false if
// the "this" pointer will come through a different
// channel.
////////////////////////////////////////////////////////////////////
bool WrapperBuilder::
synthesize_this_parameter() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::make_remap
// Access: Protected, Virtual
// Description: Allocates a new ParameterRemap object suitable to the
// indicated type.
////////////////////////////////////////////////////////////////////
ParameterRemap *WrapperBuilder::
make_remap(int def_index, CPPType *orig_type) {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
if (convert_strings) {
if (TypeManager::is_char_pointer(orig_type)) {
return new ParameterRemapCharStarToString(orig_type);
}
// If we're exporting a method of basic_string<char> itself, don't
// convert basic_string<char>'s to atomic strings.
if (def->_struct_type == (CPPStructType *)NULL ||
!TypeManager::is_basic_string_char(def->_struct_type)) {
if (TypeManager::is_basic_string_char(orig_type)) {
return new ParameterRemapBasicStringToString(orig_type);
} else if (TypeManager::is_const_ref_to_basic_string_char(orig_type)) {
return new ParameterRemapBasicStringRefToString(orig_type);
}
}
}
if (manage_reference_counts) {
if (TypeManager::is_pointer_to_base(orig_type) ||
TypeManager::is_const_ref_to_pointer_to_base(orig_type)) {
CPPType *pt_type = TypeManager::unwrap_reference(orig_type);
// Don't convert PointerTo<>'s to pointers for methods of the
// PointerTo itself!
if (def->_struct_type == (CPPStructType *)NULL ||
!(pt_type->get_local_name(&parser) == def->_struct_type->get_local_name(&parser))) {
return new ParameterRemapPTToPointer(orig_type);
}
}
}
if (TypeManager::is_reference(orig_type)) {
return new ParameterRemapReferenceToPointer(orig_type);
} else if (TypeManager::is_struct(orig_type)) {
return new ParameterRemapConcreteToPointer(orig_type);
/*
} else if (TypeManager::is_enum(orig_type) || TypeManager::is_const_ref_to_enum(orig_type)) {
return new ParameterRemapEnumToInt(orig_type);
*/
} else if (TypeManager::is_const_simple(orig_type)) {
return new ParameterRemapConstToNonConst(orig_type);
} else if (TypeManager::is_const_ref_to_simple(orig_type)) {
return new ParameterRemapReferenceToConcrete(orig_type);
} else if (TypeManager::is_pointer(orig_type) || TypeManager::is_simple(orig_type)) {
return new ParameterRemapUnchanged(orig_type);
} else {
// Here's something we have a problem with.
_is_valid = false;
return new ParameterRemapUnchanged(orig_type);
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::manage_return_value
// Access: Protected
// Description: Does any additional processing that we might want to
// do on the return value for the function, just before
// we return it. Returns the string representing the
// new return value after processing.
////////////////////////////////////////////////////////////////////
string WrapperBuilder::
manage_return_value(int def_index,
ostream &out, int indent_level,
const string &return_expr) const {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
if (def->_manage_reference_count) {
// If we're managing reference counts, and we're about to return a
// reference countable object, then increment its count.
if (return_expr == "return_value") {
// If the expression is just a variable name, we can just ref it
// directly.
output_ref(def_index, out, indent_level, return_expr);
return return_expr;
} else {
// Otherwise, we should probably assign it to a temporary first,
// so we don't invoke the function twice or something.
CPPType *type = def->_return_type->get_temporary_type();
indent(out, indent_level);
type->output_instance(out, "refcount", &parser);
out << " = " << return_expr << ";\n";
indent(out, indent_level)
<< "if (" << return_expr << " != ("
<< def->_return_type->get_new_type()->get_local_name(&parser) << ")0) {\n";
indent(out, indent_level + 2)
<< return_expr << "->ref();\n";
indent(out, indent_level)
<< "}\n";
output_ref(def_index, out, indent_level, "refcount");
return def->_return_type->temporary_to_return("refcount");
}
}
// Otherwise, just return the expression unchanged.
return return_expr;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::output_ref
// Access: Protected
// Description: Outputs the code to increment the reference count for
// the indicated variable name.
////////////////////////////////////////////////////////////////////
void WrapperBuilder::
output_ref(int def_index, ostream &out, int indent_level, const string &varname) const {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
if (def->_type == T_constructor || def->_type == T_typecast) {
// In either of these cases, we can safely assume the pointer will
// never be NULL.
indent(out, indent_level)
<< varname << "->ref();\n";
} else {
// However, in the general case, we have to check for that before
// we attempt to ref it.
indent(out, indent_level)
<< "if (" << varname << " != ("
<< def->_return_type->get_new_type()->get_local_name(&parser) << ")0) {\n";
indent(out, indent_level + 2)
<< varname << "->ref();\n";
indent(out, indent_level)
<< "}\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::get_parameter_name
// Access: Protected
// Description: Returns a suitable name for the nth parameter.
////////////////////////////////////////////////////////////////////
string WrapperBuilder::
get_parameter_name(int n) const {
/*
if (_has_this) {
if (n == 0) {
return "container";
}
n--;
}
*/
ostringstream str;
str << "param" << n;
return str.str();
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::get_parameter_expr
// Access: Protected
// Description: Returns a string that represents the expression
// associated with the nth parameter. This is just the
// nth element of pexprs if it is nonempty, or the name
// of the nth parameter is it is empty.
////////////////////////////////////////////////////////////////////
string WrapperBuilder::
get_parameter_expr(int n, const vector_string &pexprs) const {
if (n < (int)pexprs.size()) {
return pexprs[n];
}
return get_parameter_name(n);
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::get_call_str
// Access: Protected
// Description: Returns a string suitable for calling the wrapped
// function. If pexprs is nonempty, it represents
// the list of expressions that will evaluate to each
// parameter value.
////////////////////////////////////////////////////////////////////
string WrapperBuilder::
get_call_str(int def_index,
const string &container, const vector_string &pexprs) const {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
// Build up the call to the actual function.
ostringstream call;
// Getters and setters are a special case.
if (def->_type == T_getter) {
if (!container.empty()) {
call << "(" << container << ")->" << def->_expression;
} else {
call << def->_expression;
}
assert(def->_parameters.empty());
} else if (def->_type == T_setter) {
if (!container.empty()) {
call << "(" << container << ")->" << def->_expression;
} else {
call << def->_expression;
}
call << " = ";
assert(def->_parameters.size() == 1);
def->_parameters[0]._remap->pass_parameter(call, get_parameter_expr(0, pexprs));
} else {
int pn = 0;
if (def->_type == T_constructor) {
// Constructors are called differently.
call << def->_struct_type->get_local_name(&parser);
} else if (!container.empty()) {
// If we have a "this" parameter, the calling convention is also
// a bit different.
call << "(" << container << ")->" << def->_function->get_local_name();
if (def->_has_this) {
pn++;
}
} else {
call << def->_function->get_local_name(&parser);
}
call << "(";
if (pn < (int)def->_parameters.size()) {
def->_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
pn++;
while (pn < (int)def->_parameters.size()) {
call << ", ";
def->_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
pn++;
}
}
call << ")";
}
return call.str();
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::call_function
// Access: Protected
// Description: Writes a sequence of commands to the given output
// stream to call the wrapped function. The parameter
// values are taken from pexprs, if it is nonempty, or
// are assumed to be simply the names of the parameters,
// if it is empty.
//
// The return value is the expression to return, if we
// are returning a value, or the empty string if we
// return nothing.
////////////////////////////////////////////////////////////////////
string WrapperBuilder::
call_function(int def_index,
ostream &out, int indent_level, bool convert_result,
const string &container, const vector_string &pexprs) const {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
string return_expr;
if (def->_type == T_destructor) {
// A destructor wrapper is just a wrapper around the delete operator.
assert(!container.empty());
assert(def->_struct_type != (CPPStructType *)NULL);
if (TypeManager::is_reference_count(def->_struct_type)) {
// Except for a reference-count type object, in which case the
// destructor is a wrapper around unref_delete().
indent(out, indent_level)
<< "unref_delete(" << container << ");\n";
} else {
indent(out, indent_level)
<< "delete " << container << ";\n";
}
} else if (def->_type == T_typecast_method) {
// A typecast method can be invoked implicitly.
string cast_expr =
"(" + def->_return_type->get_orig_type()->get_local_name(&parser) +
")(*" + container + ")";
if (!convert_result) {
return_expr = cast_expr;
} else {
string new_str =
def->_return_type->prepare_return_expr(out, indent_level, cast_expr);
return_expr = def->_return_type->get_return_expr(new_str);
}
} else if (def->_type == T_typecast) {
// A regular typecast converts from a pointer type to another
// pointer type. (This is different from the typecast method,
// above, which converts from the concrete type to some other
// type.)
assert(!container.empty());
string cast_expr =
"(" + def->_return_type->get_orig_type()->get_local_name(&parser) +
")" + container;
if (!convert_result) {
return_expr = cast_expr;
} else {
string new_str =
def->_return_type->prepare_return_expr(out, indent_level, cast_expr);
return_expr = def->_return_type->get_return_expr(new_str);
}
} else if (def->_type == T_constructor) {
// A special case for constructors.
return_expr = "new " + get_call_str(def_index, container, pexprs);
} else if (def->_type == T_assignment_method) {
// Another special case for assignment operators.
assert(!container.empty());
indent(out, indent_level)
<< get_call_str(def_index, container, pexprs) << ";\n";
string this_expr = container;
string ref_expr = "*" + this_expr;
if (!convert_result) {
return_expr = ref_expr;
} else {
string new_str =
def->_return_type->prepare_return_expr(out, indent_level, ref_expr);
return_expr = def->_return_type->get_return_expr(new_str);
// 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)", when "return this" would do. We check for this here
// and undo it as a special case.
// There's no real good reason to do this, other than that it
// feels more satisfying to a casual perusal of the generated
// code. It *is* conceivable that some broken compilers wouldn't
// like "&(*this)", though.
if (return_expr == "&(" + ref_expr + ")" ||
return_expr == "&" + ref_expr) {
return_expr = this_expr;
}
}
} else if (def->_void_return) {
indent(out, indent_level)
<< get_call_str(def_index, container, pexprs) << ";\n";
} else {
string call = get_call_str(def_index, container, pexprs);
if (!convert_result) {
return_expr = get_call_str(def_index, container, pexprs);
} else {
if (def->_return_type->return_value_should_be_simple()) {
// We have to assign the result to a temporary first; this makes
// it a bit easier on poor old VC++.
indent(out, indent_level);
def->_return_type->get_orig_type()->output_instance(out, "result",
&parser);
out << " = " << call << ";\n";
string new_str =
def->_return_type->prepare_return_expr(out, indent_level, "result");
return_expr = def->_return_type->get_return_expr(new_str);
} else {
// This should be simple enough that we can return it directly.
string new_str =
def->_return_type->prepare_return_expr(out, indent_level, call);
return_expr = def->_return_type->get_return_expr(new_str);
}
}
}
return return_expr;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::write_spam_message
// Access: Protected
// Description: Generates the lines of code at the beginning of the
// wrapper function that output a message when the
// wrapper is called. This is output only if -spam is
// specified on the command line.
////////////////////////////////////////////////////////////////////
void WrapperBuilder::
write_spam_message(int def_index, ostream &out) const {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
if (generate_spam) {
out << "#ifndef NDEBUG\n"
<< " if (in_" << library_name << "_cat.is_spam()) {\n"
<< " in_" << library_name << "_cat.spam()\n"
<< " << \"";
write_quoted_string(out, def->_description);
out << "\\n\";\n"
<< " }\n"
<< "#endif\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::write_quoted_string
// Access: Protected
// Description: Writes the string to the given output stream, as if
// it were quoted within double quotes in a C program.
// Specifically, this escapes characters that need to be
// escaped, and otherwise leaves the string unchanged.
////////////////////////////////////////////////////////////////////
void WrapperBuilder::
write_quoted_string(ostream &out, const string &str) const {
string::const_iterator si;
for (si = str.begin(); si != str.end(); ++si) {
switch (*si) {
case '\n':
out << "\\n";
break;
case '\t':
out << "\\t";
break;
case '\\':
case '"':
out << '\\';
// fall through
default:
out << *si;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilder::indent
// Access: Public, Static
// Description:
////////////////////////////////////////////////////////////////////
ostream &WrapperBuilder::
indent(ostream &out, int indent_level) {
for (int i = 0; i < indent_level; i++) {
out << ' ';
}
return out;
}

View File

@@ -1,176 +0,0 @@
// Filename: wrapperBuilder.h
// Created by: drose (01Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef WRAPPERBUILDER_H
#define WRAPPERBUILDER_H
#include <dtoolbase.h>
#include <interrogate_interface.h>
#include <vector_string.h>
#include <vector>
class CPPInstance;
class CPPScope;
class CPPStructType;
class CPPType;
class CPPFunctionType;
class ParameterRemap;
class FunctionWriters;
////////////////////////////////////////////////////////////////////
// Class : WrapperBuilder
// Description : Contains all the information necessary to synthesize
// a wrapper around a particular function. This
// includes choosing appropriate parameter types to
// remap from the C++ function's parameter types, as
// well as actually generating wrapper code.
//
// This can wrap just one particular function signature,
// or several different function signatures with the
// same function name (e.g. function overloading). In
// the simple kinds of wrappers, like WrapperBuilderC
// and WrapperBuilderPython, this is only intended to
// wrap one function signature per wrapper, but wrappers
// that can implement function overloading directly
// (like WrapperBuilderPythonObj) will store multiple
// function signatures and implement all of them within
// the same wrapper.
//
// This is an abstract class; it doesn't actually know
// how to choose parameter types and synthesize
// wrappers; see WrapperBuilderC and
// WrapperBuilderPython.
////////////////////////////////////////////////////////////////////
class WrapperBuilder {
public:
enum Type {
T_normal,
T_constructor,
T_destructor,
T_typecast_method,
T_assignment_method,
T_typecast,
T_getter,
T_setter
};
WrapperBuilder();
virtual ~WrapperBuilder();
int add_function(CPPInstance *function, const string &description,
CPPStructType *struct_type, CPPScope *scope,
const string &function_signature, Type type,
const string &expression,
int num_default_parameters);
virtual void get_function_writers(FunctionWriters &writers);
virtual void
write_prototype(ostream &out, const string &wrapper_name) const=0;
virtual void
write_wrapper(ostream &out, const string &wrapper_name) const=0;
virtual string
get_wrapper_name(const string &library_hash_name) const=0;
virtual bool supports_atomic_strings() const=0;
virtual bool synthesize_this_parameter() const;
enum CallingConvention {
CC_c,
CC_python,
CC_python_obj,
};
virtual CallingConvention get_calling_convention() const=0;
class Parameter {
public:
bool _has_name;
string _name;
ParameterRemap *_remap;
};
typedef vector<Parameter> Parameters;
class FunctionDef {
public:
FunctionDef();
~FunctionDef();
private:
FunctionDef(const FunctionDef &copy);
void operator = (const FunctionDef &copy);
public:
Parameters _parameters;
ParameterRemap *_return_type;
bool _void_return;
bool _has_this;
bool _is_method;
Type _type;
CPPInstance *_function;
string _description;
CPPStructType *_struct_type;
CPPScope *_scope;
CPPFunctionType *_ftype;
string _function_signature;
string _expression;
int _num_default_parameters;
bool _return_value_needs_management;
FunctionIndex _return_value_destructor;
bool _manage_reference_count;
};
typedef vector<FunctionDef *> Def;
Def _def;
string _hash;
int _wrapper_index;
bool _is_valid;
protected:
virtual ParameterRemap *make_remap(int def_index, CPPType *orig_type);
string manage_return_value(int def_index,
ostream &out, int indent_level,
const string &return_expr) const;
void output_ref(int def_index, ostream &out, int indent_level, const string &varname) const;
string get_parameter_name(int n) const;
string get_parameter_expr(int n, const vector_string &pexprs) const;
string get_call_str(int def_index,
const string &container,
const vector_string &pexprs) const;
string call_function(int def_index,
ostream &out, int indent_level,
bool convert_result, const string &container,
const vector_string &pexprs = vector_string()) const;
void write_spam_message(int def_index, ostream &out) const;
void write_quoted_string(ostream &out, const string &str) const;
public:
static ostream &indent(ostream &out, int indent_level);
};
#endif

View File

@@ -1,171 +0,0 @@
// Filename: wrapperBuilderC.cxx
// Created by: drose (06Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "wrapperBuilderC.h"
#include "interrogate.h"
#include "parameterRemap.h"
#include <interrogateDatabase.h>
#include <cppInstance.h>
#include <cppFunctionType.h>
#include <cppParameterList.h>
#include <cppConstType.h>
#include <cppReferenceType.h>
#include <cppPointerType.h>
#include <cppSimpleType.h>
#include <cppStructType.h>
#include <notify.h>
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderC::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
WrapperBuilderC::
WrapperBuilderC() {
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderC::write_prototype
// Access: Public, Virtual
// Description: Generates the prototype for the wrapper function(s).
////////////////////////////////////////////////////////////////////
void WrapperBuilderC::
write_prototype(ostream &out, const string &wrapper_name) const {
for (int def_index = 0; def_index < (int)_def.size(); ++def_index) {
const FunctionDef *def = _def[def_index];
if (!output_function_names) {
// If we're not saving the function names, don't export it from
// the library.
out << "static ";
} else {
out << "extern \"C\" ";
}
if (def->_void_return) {
out << "void " << wrapper_name;
} else {
def->_return_type->get_new_type()->output_instance(out, wrapper_name, &parser);
}
out << "(";
int pn = 0;
if (pn < (int)def->_parameters.size()) {
def->_parameters[pn]._remap->get_new_type()->
output_instance(out, get_parameter_name(pn), &parser);
pn++;
while (pn < (int)def->_parameters.size()) {
out << ", ";
def->_parameters[pn]._remap->get_new_type()->
output_instance(out, get_parameter_name(pn), &parser);
pn++;
}
}
out << ");\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderC::write_wrapper
// Access: Public, Virtual
// Description: Generates a wrapper function to the indicated output
// stream.
////////////////////////////////////////////////////////////////////
void WrapperBuilderC::
write_wrapper(ostream &out, const string &wrapper_name) const {
for (int def_index = 0; def_index < (int)_def.size(); ++def_index) {
const FunctionDef *def = _def[def_index];
out << "/*\n"
<< " * C wrapper for\n"
<< " * " << def->_description << "\n"
<< " */\n";
if (!output_function_names) {
// If we're not saving the function names, don't export it from
// the library.
out << "static ";
}
if (def->_void_return) {
out << "void\n";
} else {
out << def->_return_type->get_new_type()->get_local_name(&parser) << "\n";
}
out << wrapper_name << "(";
int pn = 0;
if (pn < (int)def->_parameters.size()) {
def->_parameters[pn]._remap->get_new_type()->
output_instance(out, get_parameter_name(pn), &parser);
pn++;
while (pn < (int)def->_parameters.size()) {
out << ", ";
def->_parameters[pn]._remap->get_new_type()->
output_instance(out, get_parameter_name(pn), &parser);
pn++;
}
}
out << ") {\n";
write_spam_message(def_index, out);
string return_expr = call_function(def_index, out, 2, true, "param0");
return_expr = manage_return_value(def_index, out, 2, return_expr);
if (!return_expr.empty()) {
out << " return " << return_expr << ";\n";
}
out << "}\n\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderC::get_wrapper_name
// Access: Public, Virtual
// Description: Returns the callable name for this wrapper function.
////////////////////////////////////////////////////////////////////
string WrapperBuilderC::
get_wrapper_name(const string &library_hash_name) const {
return "_inC" + library_hash_name + _hash;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderC::supports_atomic_strings
// Access: Public, Virtual
// Description: Returns true if this kind of wrapper can support true
// atomic string objects (and not have to fiddle with
// char *).
////////////////////////////////////////////////////////////////////
bool WrapperBuilderC::
supports_atomic_strings() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderC::get_calling_convention
// Access: Public, Virtual
// Description: Returns an indication of what kind of function we are
// building.
////////////////////////////////////////////////////////////////////
WrapperBuilder::CallingConvention WrapperBuilderC::
get_calling_convention() const {
return CC_c;
}

View File

@@ -1,48 +0,0 @@
// Filename: wrapperBuilderC.h
// Created by: drose (06Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef WRAPPERBUILDERC_H
#define WRAPPERBUILDERC_H
#include <dtoolbase.h>
#include "wrapperBuilder.h"
////////////////////////////////////////////////////////////////////
// Class : WrapperBuilderC
// Description : A specialization on WrapperBuilder that builds
// C-style wrapper functions.
////////////////////////////////////////////////////////////////////
class WrapperBuilderC : public WrapperBuilder {
public:
WrapperBuilderC();
virtual void
write_prototype(ostream &out, const string &wrapper_name) const;
virtual void
write_wrapper(ostream &out, const string &wrapper_name) const;
virtual string
get_wrapper_name(const string &library_hash_name) const;
virtual bool supports_atomic_strings() const;
virtual CallingConvention get_calling_convention() const;
};
#endif

View File

@@ -1,330 +0,0 @@
// Filename: wrapperBuilderPython.cxx
// Created by: drose (07Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "wrapperBuilderPython.h"
#include "interrogate.h"
#include "parameterRemap.h"
#include "typeManager.h"
#include <interrogateDatabase.h>
#include <cppInstance.h>
#include <cppFunctionType.h>
#include <cppParameterList.h>
#include <cppConstType.h>
#include <cppReferenceType.h>
#include <cppPointerType.h>
#include <cppSimpleType.h>
#include <cppStructType.h>
#include <cppExpression.h>
#include <notify.h>
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
WrapperBuilderPython::
WrapperBuilderPython() {
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::write_prototype
// Access: Public, Virtual
// Description: Generates the prototype for the wrapper function(s).
////////////////////////////////////////////////////////////////////
void WrapperBuilderPython::
write_prototype(ostream &out, const string &wrapper_name) const {
if (!output_function_names) {
// If we're not saving the function names, don't export it from
// the library.
out << "static ";
} else {
out << "extern \"C\" ";
}
out << "PyObject *"
<< wrapper_name << "(PyObject *, PyObject *args);\n";
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::write_wrapper
// Access: Public, Virtual
// Description: Generates a wrapper function to the indicated output
// stream.
////////////////////////////////////////////////////////////////////
void WrapperBuilderPython::
write_wrapper(ostream &out, const string &wrapper_name) const {
for (int def_index = 0; def_index < (int)_def.size(); ++def_index) {
const FunctionDef *def = _def[def_index];
out << "/*\n"
<< " * Python simple wrapper for\n"
<< " * " << def->_description << "\n"
<< " */\n";
if (!output_function_names) {
// If we're not saving the function names, don't export it from
// the library.
out << "static ";
}
out << "PyObject *\n"
<< wrapper_name << "(PyObject *, PyObject *args) {\n";
write_spam_message(def_index, out);
int pn;
string format_specifiers;
string parameter_list;
string container;
vector_string pexprs;
// Make one pass through the parameter list. We will output a
// one-line temporary variable definition for each parameter, while
// simultaneously building the ParseTuple() function call and also
// the parameter expression list for call_function().
for (pn = 0; pn < (int)def->_parameters.size(); pn++) {
out << " ";
CPPType *orig_type = def->_parameters[pn]._remap->get_orig_type();
CPPType *type = def->_parameters[pn]._remap->get_new_type();
// This is the string to convert our local variable to the
// appropriate C++ type. Normally this is just a cast.
string pexpr_string =
"(" + type->get_local_name(&parser) + ")" + get_parameter_name(pn);
if (def->_parameters[pn]._remap->new_type_is_atomic_string()) {
if (TypeManager::is_char_pointer(orig_type)) {
out << "char *" << get_parameter_name(pn);
format_specifiers += "s";
parameter_list += ", &" + get_parameter_name(pn);
} else {
out << "char *" << get_parameter_name(pn)
<< "_str; int " << get_parameter_name(pn) << "_len";
format_specifiers += "s#";
parameter_list += ", &" + get_parameter_name(pn)
+ "_str, &" + get_parameter_name(pn) + "_len";
pexpr_string = "basic_string<char>(" +
get_parameter_name(pn) + "_str, " +
get_parameter_name(pn) + "_len)";
}
} else if (TypeManager::is_bool(type)) {
out << "PyObject *" << get_parameter_name(pn);
format_specifiers += "O";
parameter_list += ", &" + get_parameter_name(pn);
pexpr_string = "(PyObject_IsTrue(" + get_parameter_name(pn) + ")!=0)";
} else if (TypeManager::is_integer(type)) {
out << "int " << get_parameter_name(pn);
format_specifiers += "i";
parameter_list += ", &" + get_parameter_name(pn);
} else if (TypeManager::is_float(type)) {
out << "double " << get_parameter_name(pn);
format_specifiers += "d";
parameter_list += ", &" + get_parameter_name(pn);
} else if (TypeManager::is_char_pointer(type)) {
out << "char *" << get_parameter_name(pn);
format_specifiers += "s";
parameter_list += ", &" + get_parameter_name(pn);
} else if (TypeManager::is_pointer(type)) {
out << "int " << get_parameter_name(pn);
format_specifiers += "i";
parameter_list += ", &" + get_parameter_name(pn);
} else {
// Ignore a parameter.
out << "PyObject *" << get_parameter_name(pn);
format_specifiers += "O";
parameter_list += ", &" + get_parameter_name(pn);
}
out << ";\n";
if (def->_has_this && pn == 0) {
// The "this" parameter gets passed in separately.
container = pexpr_string;
}
pexprs.push_back(pexpr_string);
}
out << " if (PyArg_ParseTuple(args, \"" << format_specifiers
<< "\"" << parameter_list << ")) {\n";
if (track_interpreter) {
out << " in_interpreter = 0;\n";
}
if (def->_return_type->new_type_is_atomic_string()) {
// Treat strings as a special case. We don't want to format the
// return expression.
string return_expr = call_function(def_index,
out, 4, false, container, pexprs);
CPPType *type = def->_return_type->get_orig_type();
out << " ";
type->output_instance(out, "return_value", &parser);
out << " = " << return_expr << ";\n";
if (track_interpreter) {
out << " in_interpreter = 1;\n";
}
return_expr = manage_return_value(def_index, out, 4, "return_value");
test_assert(out, 4);
pack_return_value(def_index, out, return_expr);
} else {
string return_expr = call_function(def_index,
out, 4, true, container, pexprs);
if (return_expr.empty()) {
if (track_interpreter) {
out << " in_interpreter = 1;\n";
}
test_assert(out, 4);
out << " return Py_BuildValue(\"\");\n";
} else {
CPPType *type = def->_return_type->get_temporary_type();
out << " ";
type->output_instance(out, "return_value", &parser);
out << " = " << return_expr << ";\n";
if (track_interpreter) {
out << " in_interpreter = 1;\n";
}
return_expr = manage_return_value(def_index, out, 4, "return_value");
test_assert(out, 4);
pack_return_value(def_index, out, def->_return_type->temporary_to_return(return_expr));
}
}
out << " }\n";
out << " return (PyObject *)NULL;\n";
out << "}\n\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::get_wrapper_name
// Access: Public, Virtual
// Description: Returns the callable name for this wrapper function.
////////////////////////////////////////////////////////////////////
string WrapperBuilderPython::
get_wrapper_name(const string &library_hash_name) const {
return "_inP" + library_hash_name + _hash;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::supports_atomic_strings
// Access: Public, Virtual
// Description: Returns true if this kind of wrapper can support true
// atomic string objects (and not have to fiddle with
// char *).
////////////////////////////////////////////////////////////////////
bool WrapperBuilderPython::
supports_atomic_strings() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::get_calling_convention
// Access: Public, Virtual
// Description: Returns an indication of what kind of function we are
// building.
////////////////////////////////////////////////////////////////////
WrapperBuilder::CallingConvention WrapperBuilderPython::
get_calling_convention() const {
return CC_python;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::test_assert
// Access: Protected
// Description: Outputs code to check to see if an assertion has
// failed while the C++ code was executing, and report
// this failure back to Python.
////////////////////////////////////////////////////////////////////
void WrapperBuilderPython::
test_assert(ostream &out, int indent_level) const {
if (watch_asserts) {
out << "#ifndef NDEBUG\n";
indent(out, indent_level)
<< "Notify *notify = Notify::ptr();\n";
indent(out, indent_level)
<< "if (notify->has_assert_failed()) {\n";
indent(out, indent_level + 2)
<< "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n";
indent(out, indent_level + 2)
<< "notify->clear_assert_failed();\n";
indent(out, indent_level + 2)
<< "return (PyObject *)NULL;\n";
indent(out, indent_level)
<< "}\n";
out << "#endif\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPython::pack_return_value
// Access: Protected
// Description: Outputs a command to pack the indicated expression,
// of the return_type type, as a Python return value.
////////////////////////////////////////////////////////////////////
void WrapperBuilderPython::
pack_return_value(int def_index, ostream &out, string return_expr) const {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
CPPType *orig_type = def->_return_type->get_orig_type();
CPPType *type = def->_return_type->get_new_type();
out << " return Py_BuildValue(";
if (def->_return_type->new_type_is_atomic_string()) {
if (TypeManager::is_char_pointer(orig_type)) {
out << "\"s\", " << return_expr;
} else {
out << "\"s#\", " << return_expr << ".data(), "
<< return_expr << ".length()";
}
} else if (TypeManager::is_integer(type)) {
out << "\"i\", (int)(" << return_expr << ")";
} else if (TypeManager::is_float(type)) {
out << "\"d\", (double)(" << return_expr << ")";
} else if (TypeManager::is_char_pointer(type)) {
out << "\"s\", " << return_expr;
} else if (TypeManager::is_pointer(type)) {
out << "\"i\", (int)" << return_expr;
} else {
// Return None.
out << "\"\"";
}
out << ");\n";
}

View File

@@ -1,54 +0,0 @@
// Filename: wrapperBuilderPython.h
// Created by: drose (07Aug00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef WRAPPERBUILDERPYTHON_H
#define WRAPPERBUILDERPYTHON_H
#include <dtoolbase.h>
#include "wrapperBuilder.h"
////////////////////////////////////////////////////////////////////
// Class : WrapperBuilderPython
// Description : A specialization on WrapperBuilder that builds
// simple Python wrapper functions, simple functions
// that call C++ methods directly given a handle and a
// set of parameters.
////////////////////////////////////////////////////////////////////
class WrapperBuilderPython : public WrapperBuilder {
public:
WrapperBuilderPython();
virtual void
write_prototype(ostream &out, const string &wrapper_name) const;
virtual void
write_wrapper(ostream &out, const string &wrapper_name) const;
virtual string
get_wrapper_name(const string &library_hash_name) const;
virtual bool supports_atomic_strings() const;
virtual CallingConvention get_calling_convention() const;
protected:
void test_assert(ostream &out, int indent_level) const;
void pack_return_value(int def_index, ostream &out, string return_expr) const;
};
#endif

View File

@@ -1,458 +0,0 @@
// Filename: wrapperBuilderPythonObj.cxx
// Created by: drose (11Sep01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "wrapperBuilderPythonObj.h"
#include "interrogate.h"
#include "parameterRemap.h"
#include "typeManager.h"
#include "functionWriterPtrFromPython.h"
#include "functionWriterPtrToPython.h"
#include "functionWriters.h"
#include <interrogateDatabase.h>
#include <cppInstance.h>
#include <cppFunctionType.h>
#include <cppParameterList.h>
#include <cppConstType.h>
#include <cppReferenceType.h>
#include <cppPointerType.h>
#include <cppSimpleType.h>
#include <cppStructType.h>
#include <cppExpression.h>
#include <notify.h>
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
WrapperBuilderPythonObj::
WrapperBuilderPythonObj() {
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::get_function_writers
// Access: Public, Virtual
// Description: Adds whatever list of FunctionWriters might be needed
// for this particular WrapperBuilder. These will be
// generated to the output source file before
// write_wrapper() is called.
////////////////////////////////////////////////////////////////////
void WrapperBuilderPythonObj::
get_function_writers(FunctionWriters &writers) {
for (int def_index = 0; def_index < (int)_def.size(); ++def_index) {
const FunctionDef *def = _def[def_index];
if (def->_is_method) {
FunctionWriterPtrFromPython *writer =
new FunctionWriterPtrFromPython(def->_struct_type);
writers.add_writer(writer);
}
int pn;
for (pn = 0; pn < (int)def->_parameters.size(); pn++) {
CPPType *type = def->_parameters[pn]._remap->get_new_type();
if (def->_parameters[pn]._remap->new_type_is_atomic_string()) {
} else if (TypeManager::is_bool(type)) {
} else if (TypeManager::is_integer(type)) {
} else if (TypeManager::is_float(type)) {
} else if (TypeManager::is_char_pointer(type)) {
} else if (TypeManager::is_pointer(type)) {
FunctionWriterPtrFromPython *writer =
new FunctionWriterPtrFromPython(type);
writers.add_writer(writer);
}
}
CPPType *type = def->_return_type->get_new_type();
if (def->_return_type->new_type_is_atomic_string()) {
} else if (TypeManager::is_integer(type)) {
} else if (TypeManager::is_float(type)) {
} else if (TypeManager::is_char_pointer(type)) {
} else if (TypeManager::is_pointer(type)) {
FunctionWriterPtrToPython *writer =
new FunctionWriterPtrToPython(type);
writers.add_writer(writer);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::write_prototype
// Access: Public, Virtual
// Description: Generates the prototype for the wrapper function(s).
////////////////////////////////////////////////////////////////////
void WrapperBuilderPythonObj::
write_prototype(ostream &out, const string &wrapper_name) const {
if (!output_function_names) {
// If we're not saving the function names, don't export it from
// the library.
out << "static ";
} else {
out << "extern \"C\" ";
}
out << "PyObject *"
<< wrapper_name << "(PyObject *self, PyObject *args);\n";
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::write_wrapper
// Access: Public, Virtual
// Description: Generates a wrapper function to the indicated output
// stream.
////////////////////////////////////////////////////////////////////
void WrapperBuilderPythonObj::
write_wrapper(ostream &out, const string &wrapper_name) const {
bool any_is_method = false;
out << "/*\n"
<< " * Python object wrapper for\n";
int def_index;
for (def_index = 0; def_index < (int)_def.size(); ++def_index) {
const FunctionDef *def = _def[def_index];
out << " * " << def->_description << "\n";
if (def->_is_method) {
any_is_method = true;
}
}
out << " */\n";
if (!output_function_names) {
// If we're not saving the function names, don't export it from
// the library.
out << "static ";
}
if (any_is_method) {
out << "PyObject *\n"
<< wrapper_name << "(PyObject *self, PyObject *args) {\n";
} else {
out << "PyObject *\n"
<< wrapper_name << "(PyObject *, PyObject *args) {\n";
}
write_spam_message(0, out);
string expected_params = "Arguments must match one of:";
for (def_index = 0; def_index < (int)_def.size(); ++def_index) {
const FunctionDef *def = _def[def_index];
out << " {\n"
<< " /* " << def->_description << " */\n"
<< "\n";
string thisptr;
if (def->_is_method) {
// Declare a "thisptr" variable.
thisptr = "thisptr";
FunctionWriterPtrFromPython *writer =
new FunctionWriterPtrFromPython(def->_struct_type);
out << " ";
writer->get_pointer_type()->output_instance(out, thisptr, &parser);
out << ";\n"
<< " if (!" << writer->get_name() << "(self, &thisptr)) {\n"
<< " return (PyObject *)NULL;\n"
<< " }\n";
delete writer;
}
string format_specifiers;
string parameter_list;
vector_string pexprs;
// Make one pass through the parameter list. We will output a
// one-line temporary variable definition for each parameter, while
// simultaneously building the ParseTuple() function call and also
// the parameter expression list for call_function().
expected_params += "\\n ";
expected_params += _def[0]->_function->get_simple_name();
expected_params += "(";
int pn;
for (pn = 0; pn < (int)def->_parameters.size(); pn++) {
if (pn != 0) {
expected_params += ", ";
}
out << " ";
CPPType *orig_type = def->_parameters[pn]._remap->get_orig_type();
CPPType *type = def->_parameters[pn]._remap->get_new_type();
// This is the string to convert our local variable to the
// appropriate C++ type. Normally this is just a cast.
string pexpr_string =
"(" + type->get_local_name(&parser) + ")" + get_parameter_name(pn);
if (def->_parameters[pn]._remap->new_type_is_atomic_string()) {
if (TypeManager::is_char_pointer(orig_type)) {
out << "char *" << get_parameter_name(pn);
format_specifiers += "s";
parameter_list += ", &" + get_parameter_name(pn);
} else {
out << "char *" << get_parameter_name(pn)
<< "_str; int " << get_parameter_name(pn) << "_len";
format_specifiers += "s#";
parameter_list += ", &" + get_parameter_name(pn)
+ "_str, &" + get_parameter_name(pn) + "_len";
pexpr_string = "basic_string<char>(" +
get_parameter_name(pn) + "_str, " +
get_parameter_name(pn) + "_len)";
}
expected_params += "string";
} else if (TypeManager::is_bool(type)) {
out << "PyObject *" << get_parameter_name(pn);
format_specifiers += "O";
parameter_list += ", &" + get_parameter_name(pn);
pexpr_string = "(PyObject_IsTrue(" + get_parameter_name(pn) + ")!=0)";
expected_params += "bool";
} else if (TypeManager::is_integer(type)) {
out << "int " << get_parameter_name(pn);
format_specifiers += "i";
parameter_list += ", &" + get_parameter_name(pn);
expected_params += "integer";
} else if (TypeManager::is_float(type)) {
out << "double " << get_parameter_name(pn);
format_specifiers += "d";
parameter_list += ", &" + get_parameter_name(pn);
expected_params += "float";
} else if (TypeManager::is_char_pointer(type)) {
out << "char *" << get_parameter_name(pn);
format_specifiers += "s";
parameter_list += ", &" + get_parameter_name(pn);
expected_params += "string";
} else if (TypeManager::is_pointer(type)) {
out << "int " << get_parameter_name(pn);
format_specifiers += "i";
parameter_list += ", &" + get_parameter_name(pn);
expected_params += "pointer";
} else {
// Ignore a parameter.
out << "PyObject *" << get_parameter_name(pn);
format_specifiers += "O";
parameter_list += ", &" + get_parameter_name(pn);
expected_params += "ignored";
}
if (def->_parameters[pn]._has_name) {
expected_params += " " + def->_parameters[pn]._name;
}
out << ";\n";
pexprs.push_back(pexpr_string);
}
expected_params += ")";
out << " if (PyArg_ParseTuple(args, \"" << format_specifiers
<< "\"" << parameter_list << ")) {\n";
if (track_interpreter) {
out << " in_interpreter = 0;\n";
}
if (def->_return_type->new_type_is_atomic_string()) {
// Treat strings as a special case. We don't want to format the
// return expression.
string return_expr = call_function(def_index,
out, 6, false, thisptr, pexprs);
CPPType *type = def->_return_type->get_orig_type();
out << " ";
type->output_instance(out, "return_value", &parser);
out << " = " << return_expr << ";\n";
if (track_interpreter) {
out << " in_interpreter = 1;\n";
}
return_expr = manage_return_value(def_index, out, 6, "return_value");
test_assert(out, 6);
pack_return_value(def_index, out, return_expr);
} else {
string return_expr = call_function(def_index,
out, 6, true, thisptr, pexprs);
if (return_expr.empty()) {
if (track_interpreter) {
out << " in_interpreter = 1;\n";
}
test_assert(out, 6);
out << " return Py_BuildValue(\"\");\n";
} else {
CPPType *type = def->_return_type->get_temporary_type();
out << " ";
type->output_instance(out, "return_value", &parser);
out << " = " << return_expr << ";\n";
if (track_interpreter) {
out << " in_interpreter = 1;\n";
}
return_expr = manage_return_value(def_index, out, 6, "return_value");
test_assert(out, 6);
pack_return_value(def_index, out, def->_return_type->temporary_to_return(return_expr));
}
}
out << " }\n"
<< " PyErr_Clear();\n" // Clear the error generated by ParseTuple()
<< " }\n";
}
// Invalid parameters. Generate an error exception. (We don't rely
// on the error already generated by ParseTuple(), because it only
// reports the error for one flavor of the function, whereas we
// might accept multiple flavors for the different overloaded
// C++ function signatures.
out << " PyErr_SetString(PyExc_TypeError, \"" << expected_params << "\");\n"
<< " return (PyObject *)NULL;\n";
out << "}\n\n";
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::get_wrapper_name
// Access: Public, Virtual
// Description: Returns the callable name for this wrapper function.
////////////////////////////////////////////////////////////////////
string WrapperBuilderPythonObj::
get_wrapper_name(const string &library_hash_name) const {
return "_inM" + library_hash_name + _hash;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::supports_atomic_strings
// Access: Public, Virtual
// Description: Returns true if this kind of wrapper can support true
// atomic string objects (and not have to fiddle with
// char *).
////////////////////////////////////////////////////////////////////
bool WrapperBuilderPythonObj::
supports_atomic_strings() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::synthesize_this_parameter
// Access: Public, Virtual
// Description: Returns true if this particular wrapper type requires
// an explicit "this" parameter to be added to the
// function parameter list when appropriate, or false if
// the "this" pointer will come through a different
// channel.
////////////////////////////////////////////////////////////////////
bool WrapperBuilderPythonObj::
synthesize_this_parameter() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::get_calling_convention
// Access: Public, Virtual
// Description: Returns an indication of what kind of function we are
// building.
////////////////////////////////////////////////////////////////////
WrapperBuilder::CallingConvention WrapperBuilderPythonObj::
get_calling_convention() const {
return CC_python_obj;
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::test_assert
// Access: Protected
// Description: Outputs code to check to see if an assertion has
// failed while the C++ code was executing, and report
// this failure back to Python.
////////////////////////////////////////////////////////////////////
void WrapperBuilderPythonObj::
test_assert(ostream &out, int indent_level) const {
if (watch_asserts) {
out << "#ifndef NDEBUG\n";
indent(out, indent_level)
<< "Notify *notify = Notify::ptr();\n";
indent(out, indent_level)
<< "if (notify->has_assert_failed()) {\n";
indent(out, indent_level + 2)
<< "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n";
indent(out, indent_level + 2)
<< "notify->clear_assert_failed();\n";
indent(out, indent_level + 2)
<< "return (PyObject *)NULL;\n";
indent(out, indent_level)
<< "}\n";
out << "#endif\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: WrapperBuilderPythonObj::pack_return_value
// Access: Protected
// Description: Outputs a command to pack the indicated expression,
// of the return_type type, as a Python return value.
////////////////////////////////////////////////////////////////////
void WrapperBuilderPythonObj::
pack_return_value(int def_index, ostream &out, string return_expr) const {
assert(def_index >= 0 && def_index < (int)_def.size());
const FunctionDef *def = _def[def_index];
CPPType *orig_type = def->_return_type->get_orig_type();
CPPType *type = def->_return_type->get_new_type();
if (def->_return_type->new_type_is_atomic_string()) {
if (TypeManager::is_char_pointer(orig_type)) {
out << " return PyString_FromString(" << return_expr << ");\n";
} else {
out << " return PyString_FromStringAndSize("
<< return_expr << ".data(), " << return_expr << ".length());\n";
}
} else if (TypeManager::is_integer(type)) {
out << " return PyInt_FromLong("
<< return_expr << ");\n";
} else if (TypeManager::is_float(type)) {
out << " return PyFloat_FromDouble("
<< return_expr << ");\n";
} else if (TypeManager::is_char_pointer(type)) {
out << " return PyString_FromString(" << return_expr << ");\n";
} else if (TypeManager::is_pointer(type)) {
bool caller_manages = def->_return_value_needs_management;
FunctionWriterPtrToPython *writer =
new FunctionWriterPtrToPython(type);
out << " return " << writer->get_name() << "(" << return_expr
<< ", " << caller_manages << ");\n";
} else {
// Return None.
out << " return Py_BuildValue(\"\");\n";
}
}

View File

@@ -1,56 +0,0 @@
// Filename: wrapperBuilderPythonObj.h
// Created by: drose (11Sep01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef WRAPPERBUILDERPYTHONOBJ_H
#define WRAPPERBUILDERPYTHONOBJ_H
#include "dtoolbase.h"
#include "wrapperBuilder.h"
////////////////////////////////////////////////////////////////////
// Class : WrapperBuilderPythonObj
// Description : A specialization on WrapperBuilder that builds
// sophisticated Python wrapper functions that get
// assembled into Python methods, and make the C++
// objects appeart directly as Python objects.
////////////////////////////////////////////////////////////////////
class WrapperBuilderPythonObj : public WrapperBuilder {
public:
WrapperBuilderPythonObj();
virtual void get_function_writers(FunctionWriters &writers);
virtual void
write_prototype(ostream &out, const string &wrapper_name) const;
virtual void
write_wrapper(ostream &out, const string &wrapper_name) const;
virtual string
get_wrapper_name(const string &library_hash_name) const;
virtual bool supports_atomic_strings() const;
virtual bool synthesize_this_parameter() const;
virtual CallingConvention get_calling_convention() const;
protected:
void test_assert(ostream &out, int indent_level) const;
void pack_return_value(int def_index, ostream &out, string return_expr) const;
};
#endif