*** empty log message ***

This commit is contained in:
Roger Hughston 2005-05-23 21:04:31 +00:00
parent 465de6c85a
commit 63290756fe
49 changed files with 3834 additions and 183 deletions

View File

@ -16,6 +16,7 @@
interfaceMakerC.h \
interfaceMakerPython.h interfaceMakerPythonObj.h \
interfaceMakerPythonSimple.h \
interfaceMakerPythonNative.h \
interrogate.h interrogateBuilder.h parameterRemap.I \
parameterRemap.h parameterRemapBasicStringRefToString.h \
parameterRemapBasicStringToString.h \
@ -37,6 +38,7 @@
interfaceMakerC.cxx \
interfaceMakerPython.cxx interfaceMakerPythonObj.cxx \
interfaceMakerPythonSimple.cxx \
interfaceMakerPythonNative.cxx \
interrogate.cxx interrogateBuilder.cxx parameterRemap.cxx \
parameterRemapBasicStringRefToString.cxx \
parameterRemapBasicStringToString.cxx \

View File

@ -18,7 +18,7 @@
#include "functionRemap.h"
#include "typeManager.h"
#include "interrogate.h"
#include "interrogate.h"
#include "parameterRemap.h"
#include "parameterRemapThis.h"
#include "interfaceMaker.h"
@ -32,6 +32,8 @@
#include "interrogateType.h"
#include "notify.h"
extern bool inside_python_native;
////////////////////////////////////////////////////////////////////
// Function: FunctionRemap::Constructor
// Access: Public
@ -43,6 +45,7 @@ FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc,
InterfaceMaker *interface) {
_return_type = (ParameterRemap *)NULL;
_void_return = true;
_ForcedVoidReturn = false;
_has_this = false;
_first_true_parameter = 0;
_num_default_parameters = num_default_parameters;
@ -98,8 +101,7 @@ get_parameter_name(int n) const {
// are returning a value, or the empty string if we
// return nothing.
////////////////////////////////////////////////////////////////////
string FunctionRemap::
call_function(ostream &out, int indent_level, bool convert_result,
string FunctionRemap::call_function(ostream &out, int indent_level, bool convert_result,
const string &container, const vector_string &pexprs) const {
string return_expr;
@ -114,8 +116,10 @@ call_function(ostream &out, int indent_level, bool convert_result,
InterfaceMaker::indent(out, indent_level)
<< "unref_delete(" << container << ");\n";
} else {
InterfaceMaker::indent(out, indent_level)
<< "delete " << container << ";\n";
if(inside_python_native)
InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self); \n";
else
InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n";
}
} else if (_type == T_typecast_method) {
@ -342,7 +346,8 @@ get_call_str(const string &container, const vector_string &pexprs) const {
call << _expression;
}
} else if (_type == T_setter) {
} else if (_type == T_setter)
{
if (!container.empty()) {
call << "(" << container << ")->" << _expression;
} else {
@ -353,6 +358,7 @@ get_call_str(const string &container, const vector_string &pexprs) const {
_parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs));
} else {
if (_type == T_constructor) {
// Constructors are called differently.
call << _cpptype->get_local_name(&parser);
@ -547,6 +553,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface) {
// If our return type isn't something we can deal with, treat the
// function as if it returns NULL.
_void_return = true;
_ForcedVoidReturn = true;
CPPType *void_type = TypeManager::get_void_type();
_return_type = interface->remap_parameter(_cpptype, void_type);
assert(_return_type != (ParameterRemap *)NULL);

View File

@ -87,6 +87,7 @@ public:
Parameters _parameters;
ParameterRemap *_return_type;
bool _void_return;
bool _ForcedVoidReturn;
bool _has_this;
int _first_true_parameter;
int _num_default_parameters;
@ -109,16 +110,10 @@ public:
CPPFunctionType *_ftype;
bool _is_valid;
private:
string
get_call_str(const string &container, const vector_string &pexprs) const;
string
get_parameter_expr(int n, const vector_string &pexprs) const;
bool
setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface);
string get_call_str(const string &container, const vector_string &pexprs) const;
string get_parameter_expr(int n, const vector_string &pexprs) const;
bool setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface);
};
#endif

View File

@ -41,8 +41,9 @@
#include "cppParameterList.h"
#include "notify.h"
static InterrogateType dummy_type;
InterrogateType dummy_type;
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::Function::Constructor
// Access: Public
@ -58,7 +59,7 @@ Function(const string &name,
{
_has_this = false;
}
////////////////////////////////////////////////////////////////////
// Function: InterfaceMaker::Function::Destructor
// Access: Public
@ -135,45 +136,83 @@ void InterfaceMaker::
generate_wrappers() {
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
// We use a while loop rather than a simple for loop, because we
// might increase the number of types recursively during the
// traversal.
int ti = 0;
while (ti < idb->get_num_all_types()) {
TypeIndex type_index = idb->get_all_type(ti);
record_object(type_index);
while (ti < idb->get_num_all_types())
{
TypeIndex type_index = idb->get_all_type(ti);
record_object(type_index);
if(interrogate_type_is_enum(ti))
{
int enum_count = interrogate_type_number_of_enum_values(ti);
for(int xx = 0; xx< enum_count; xx++)
{
// printf(" PyModule_AddIntConstant(module,\"%s\",%d)\n",interrogate_type_enum_value_name(ti,xx),interrogate_type_enum_value(ti,xx));
}
}
++ti;
// printf(" New Type %d\n",ti);
}
int gi = 0;
while( gi = idb->get_num_global_elements())
{
printf(" Global Type = %d",gi);
TypeIndex type_index = idb->get_global_element(gi);
record_object(type_index);
}
int num_functions = idb->get_num_global_functions();
for (int fi = 0; fi < num_functions; fi++) {
for (int fi = 0; fi < num_functions; fi++)
{
FunctionIndex func_index = idb->get_global_function(fi);
record_function(dummy_type, func_index);
}
int num_manifests = idb->get_num_global_manifests();
for (int mi = 0; mi < num_manifests; mi++) {
for (int mi = 0; mi < num_manifests; mi++)
{
ManifestIndex manifest_index = idb->get_global_manifest(mi);
const InterrogateManifest &iman = idb->get_manifest(manifest_index);
if (iman.has_getter()) {
if (iman.has_getter())
{
FunctionIndex func_index = iman.get_getter();
record_function(dummy_type, func_index);
}
printf(" Manafests %d\n",mi);
}
int num_elements = idb->get_num_global_elements();
for (int ei = 0; ei < num_elements; ei++) {
for (int ei = 0; ei < num_elements; ei++)
{
printf(" Element %d\n",ei);
ElementIndex element_index = idb->get_global_element(ei);
const InterrogateElement &ielement = idb->get_element(element_index);
if (ielement.has_getter()) {
if (ielement.has_getter())
{
FunctionIndex func_index = ielement.get_getter();
record_function(dummy_type, func_index);
}
if (ielement.has_setter()) {
if (ielement.has_setter())
{
FunctionIndex func_index = ielement.get_setter();
record_function(dummy_type, func_index);
}
}
}
////////////////////////////////////////////////////////////////////
@ -195,7 +234,7 @@ write_includes(ostream &) {
// write_functions().
////////////////////////////////////////////////////////////////////
void InterfaceMaker::
write_prototypes(ostream &out) {
write_prototypes(ostream &out,ostream *out_h) {
_function_writers.write_prototypes(out);
}
@ -217,7 +256,7 @@ write_functions(ostream &out) {
// support a module file.
////////////////////////////////////////////////////////////////////
void InterfaceMaker::
write_module(ostream &, InterrogateModuleDef *) {
write_module(ostream &, ostream *out_h,InterrogateModuleDef *) {
}
@ -256,7 +295,8 @@ remap_parameter(CPPType *struct_type, CPPType *param_type) {
if (manage_reference_counts) {
if (TypeManager::is_pointer_to_base(param_type) ||
TypeManager::is_const_ref_to_pointer_to_base(param_type)) {
TypeManager::is_const_ref_to_pointer_to_base(param_type))
{
CPPType *pt_type = TypeManager::unwrap_reference(param_type);
// Don't convert PointerTo<>'s to pointers for methods of the
@ -370,15 +410,18 @@ make_function_remap(const InterrogateType &itype,
CPPInstance *cppfunc, int num_default_parameters) {
FunctionRemap *remap =
new FunctionRemap(itype, ifunc, cppfunc, num_default_parameters, this);
if (remap->_is_valid) {
if (separate_overloading()) {
if (remap->_is_valid)
{
if (separate_overloading())
{
hash_function_signature(remap);
remap->_unique_name =
get_unique_prefix() + _def->library_hash_name + remap->_hash;
remap->_wrapper_name =
get_wrapper_prefix() + _def->library_hash_name + remap->_hash;
remap->_reported_name = remap->_wrapper_name;
if (true_wrapper_names) {
if (true_wrapper_names)
{
remap->_reported_name =
InterrogateBuilder::clean_identifier(remap->_cppfunc->get_local_name(&parser));
}
@ -454,17 +497,21 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
Function *func = new Function(wrapper_name, itype, ifunc);
_functions.push_back(func);
// printf(" Function Name = %s\n",ifunc.get_name().c_str());
// Now get all the valid FunctionRemaps for the function.
if (ifunc._instances != (InterrogateFunction::Instances *)NULL) {
if (ifunc._instances != (InterrogateFunction::Instances *)NULL)
{
InterrogateFunction::Instances::const_iterator ii;
for (ii = ifunc._instances->begin();
ii != ifunc._instances->end();
++ii) {
for (ii = ifunc._instances->begin();ii != ifunc._instances->end();++ii)
{
CPPInstance *cppfunc = (*ii).second;
CPPFunctionType *ftype = cppfunc->_type->as_function_type();
int max_default_parameters = 0;
if (separate_overloading()) {
if (separate_overloading())
{
// Count up the number of default parameters this function might
// take.
CPPParameterList *parameters = ftype->_parameters;
@ -556,16 +603,18 @@ record_object(TypeIndex type_index) {
Function *function;
int num_constructors = itype.number_of_constructors();
for (int ci = 0; ci < num_constructors; ci++) {
function = record_function(itype, itype.get_constructor(ci));
object->_constructors.push_back(function);
}
int num_constructors = itype.number_of_constructors();
for (int ci = 0; ci < num_constructors; ci++)
{
function = record_function(itype, itype.get_constructor(ci));
object->_constructors.push_back(function);
}
if (itype.has_destructor() && !itype.destructor_is_inherited()) {
function = record_function(itype, itype.get_destructor());
object->_destructor = function;
}
if (itype.has_destructor() && !itype.destructor_is_inherited())
{
function = record_function(itype, itype.get_destructor());
object->_destructor = function;
}
int num_methods = itype.number_of_methods();
int mi;
@ -581,11 +630,14 @@ record_object(TypeIndex type_index) {
}
int num_derivations = itype.number_of_derivations();
for (int di = 0; di < num_derivations; di++) {
if (itype.derivation_has_upcast(di)) {
for (int di = 0; di < num_derivations; di++)
{
if (itype.derivation_has_upcast(di))
{
record_function(itype, itype.derivation_get_upcast(di));
}
if (itype.derivation_has_downcast(di)) {
if (itype.derivation_has_downcast(di))
{
// Downcasts are methods of the base class, not the child class.
TypeIndex base_type_index = itype.get_derivation(di);
const InterrogateType &base_type = idb->get_type(base_type_index);
@ -594,21 +646,25 @@ record_object(TypeIndex type_index) {
}
int num_elements = itype.number_of_elements();
for (int ei = 0; ei < num_elements; ei++) {
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()) {
if (ielement.has_getter())
{
FunctionIndex func_index = ielement.get_getter();
record_function(itype, func_index);
}
if (ielement.has_setter()) {
if (ielement.has_setter())
{
FunctionIndex func_index = ielement.get_setter();
record_function(itype, func_index);
}
}
int num_nested = itype.number_of_nested_types();
for (int ni = 0; ni < num_nested; ni++) {
for (int ni = 0; ni < num_nested; ni++)
{
TypeIndex nested_index = itype.get_nested_type(ni);
record_object(nested_index);
}
@ -796,3 +852,4 @@ write_spam_message(ostream &out, FunctionRemap *remap) const {
out << "\\n\";\n"
" }\n";
}

View File

@ -56,13 +56,13 @@ public:
virtual void generate_wrappers();
virtual void write_includes(ostream &out);
virtual void write_prototypes(ostream &out);
virtual void write_prototypes(ostream &out, ostream *out_h);
virtual void write_functions(ostream &out);
virtual void write_module_support(ostream &out,ostream *out_h,InterrogateModuleDef *moduledefdef) {};
virtual void write_module(ostream &out, InterrogateModuleDef *def);
virtual void write_module(ostream &out, ostream *out_h,InterrogateModuleDef *def);
virtual ParameterRemap *
remap_parameter(CPPType *struct_type, CPPType *param_type);
virtual ParameterRemap * remap_parameter(CPPType *struct_type, CPPType *param_type);
virtual bool synthesize_this_parameter();
virtual bool separate_overloading();
@ -71,7 +71,7 @@ public:
static ostream &indent(ostream &out, int indent_level);
protected:
public:
class Function {
public:
Function(const string &name,
@ -126,8 +126,7 @@ protected:
record_function_wrapper(InterrogateFunction &ifunc,
FunctionWrapperIndex wrapper_index);
Object *
record_object(TypeIndex type_index);
virtual Object * record_object(TypeIndex type_index);
void hash_function_signature(FunctionRemap *remap);

View File

@ -15,7 +15,7 @@
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "interfaceMakerC.h"
#include "interrogateBuilder.h"
#include "interrogate.h"
@ -56,7 +56,7 @@ InterfaceMakerC::
// write_functions().
////////////////////////////////////////////////////////////////////
void InterfaceMakerC::
write_prototypes(ostream &out) {
write_prototypes(ostream &out,ostream *out_h) {
Functions::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
@ -64,7 +64,7 @@ write_prototypes(ostream &out) {
}
out << "\n";
InterfaceMaker::write_prototypes(out);
InterfaceMaker::write_prototypes(out,out_h);
}
////////////////////////////////////////////////////////////////////

View File

@ -37,7 +37,7 @@ public:
InterfaceMakerC(InterrogateModuleDef *def);
virtual ~InterfaceMakerC();
virtual void write_prototypes(ostream &out);
virtual void write_prototypes(ostream &out,ostream *out_h);
virtual void write_functions(ostream &out);
virtual bool synthesize_this_parameter();

View File

@ -47,7 +47,11 @@ write_includes(ostream &out) {
<< " #include \"Python/Python.h\"\n"
<< "#else\n"
<< " #include \"Python.h\"\n"
<< "#endif\n\n";
<< "#endif\n"
<< "#ifdef HAVE_LONG_LONG\n"
<< "#undef HAVE_LONG_LONG\n"
<< "#endif \n";
}
////////////////////////////////////////////////////////////////////

View File

@ -40,7 +40,7 @@ public:
virtual void write_includes(ostream &out);
protected:
void test_assert(ostream &out, int indent_level) const;
virtual void test_assert(ostream &out, int indent_level) const;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,119 @@
// Filename: InterfaceMakerPythonNative.h
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef INTERFACEMAKERPYTHONNATIVE_H
#define INTERFACEMAKERPYTHONNATIVE_H
#include "map"
#include "set"
#include "dtoolbase.h"
#include "interfaceMakerPython.h"
#include "interrogate_interface.h"
#include "cppStructType.h"
class FunctionRemap;
////////////////////////////////////////////////////////////////////
// Class : InterfaceMakerPythonNative
// Description : An InterfaceMaker for generating complex Python
// function wrappers around C++ code.
////////////////////////////////////////////////////////////////////
class InterfaceMakerPythonNative : public InterfaceMakerPython
{
public:
InterfaceMakerPythonNative(InterrogateModuleDef *def);
virtual ~InterfaceMakerPythonNative();
virtual void write_prototypes(ostream &out,ostream *out_h);
void write_prototypes_class(ostream &out,ostream *out_h, Object * obj) ;
void write_prototypes_class_external(ostream &out, Object * obj);
virtual void write_functions(ostream &out);
virtual void write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def);
virtual void write_module_support(ostream &out, ostream *out_h,InterrogateModuleDef *moduledefdef);
void write_module_class(ostream &out, Object *cls);
virtual void write_sub_module(ostream &out, Object *obj);
virtual bool synthesize_this_parameter();
virtual Object *record_object(TypeIndex type_index);
protected:
virtual string get_wrapper_prefix();
virtual string get_unique_prefix();
virtual void record_function_wrapper(InterrogateFunction &ifunc,
FunctionWrapperIndex wrapper_index);
virtual void generate_wrappers();
private:
void write_prototype_for_name(ostream &out, Function *func, const std::string &name);
void write_prototype_for(ostream &out, Function *func);
void write_function_for_name(ostream &out, Function *func, const std::string &name, const std::string &PreProcess, const std::string &ClassName);
void write_function_for_top(ostream &out, Function *func, const std::string &PreProcess);
void write_function_instance(ostream &out, Function *func,
FunctionRemap *remap , string &expected_params, int indent_level, bool errors_fatal, ostream &forwarddecl, const std::string &functionnamestr ) ;
void write_function_forset(ostream &out, InterfaceMaker::Function *func,
std::set< FunctionRemap *> &remaps, string &expected_params, int indent_level , ostream &forwarddecl,const std::string &functionname) ;
void pack_return_value(ostream &out, int indent_level,
FunctionRemap *remap, std::string return_expr , ostream &forwarddecl);
void pack_return_value_tnit(ostream &out, int indent_level,
FunctionRemap *remap, string return_expr) ;
void write_class_prototypes(ostream &out) ;
void write_ClasseDeclarations(ostream &out , ostream *out_h,Object * obj);
void write_ClasseDetails(ostream &out, Object * obj);
void do_assert_init(ostream &out, int indent_level, bool constructor) const;
public:
bool isRemapLegal( FunctionRemap &remap);
bool isFunctionLegal( Function *func);
bool isCppTypeLegal(CPPType *ctype);
bool isExportThisRun(CPPType *ctype);
bool isExportThisRun(Function *func);
bool isFunctionWithThis( Function *func);
bool IsRunTimeTyped(const InterrogateType &itype);
// comunicates the cast capabilites among methods..
struct CastDetails
{
CPPStructType *_structType;
std::string _to_class_name;
std::string _up_cast_string;
bool _can_downcast;
bool _is_legal_py_class;
};
void InterfaceMakerPythonNative::GetValideChildClasses( std::map< std::string ,CastDetails > &answer, CPPStructType * inclass, const std::string &up_cast_seed = "", bool downcastposible = true);
bool DoesInheritFromIsClass( const CPPStructType * inclass, const std::string &name);
bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); };
void WriteCreateInstance(ostream &out, int indent_level, std::string &return_expr, std::string &ows_memory_flag,const std::string &class_name, CPPType *ctype);
bool HasAGetKeyFunction(const InterrogateType &itype_class);
bool NeedsAStrFunction(const InterrogateType &itype_class);
bool NeedsAReprFunction(const InterrogateType &itype_class);
// stash the forwad declarations for this compile pass..
std::set< std::string > _external_imports;
};
#endif

View File

@ -15,7 +15,7 @@
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "interfaceMakerPythonObj.h"
#include "interrogateBuilder.h"
#include "interrogate.h"
@ -58,7 +58,7 @@ InterfaceMakerPythonObj::
// write_functions().
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonObj::
write_prototypes(ostream &out) {
write_prototypes(ostream &out,ostream *out_h) {
Functions::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
@ -66,7 +66,7 @@ write_prototypes(ostream &out) {
}
out << "\n";
InterfaceMakerPython::write_prototypes(out);
InterfaceMakerPython::write_prototypes(out,out_h);
}
////////////////////////////////////////////////////////////////////
@ -102,8 +102,8 @@ write_functions(ostream &out) {
// support a module file.
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonObj::
write_module(ostream &out, InterrogateModuleDef *def) {
InterfaceMakerPython::write_module(out, def);
write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
InterfaceMakerPython::write_module(out,out_h, def);
out << "static PyMethodDef python_obj_funcs[] = {\n";

View File

@ -44,10 +44,10 @@ public:
InterfaceMakerPythonObj(InterrogateModuleDef *def);
virtual ~InterfaceMakerPythonObj();
virtual void write_prototypes(ostream &out);
virtual void write_prototypes(ostream &out,ostream *out_h);
virtual void write_functions(ostream &out);
virtual void write_module(ostream &out, InterrogateModuleDef *def);
virtual void write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def);
virtual bool synthesize_this_parameter();

View File

@ -11,7 +11,7 @@
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
@ -56,7 +56,7 @@ InterfaceMakerPythonSimple::
// write_functions().
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonSimple::
write_prototypes(ostream &out) {
write_prototypes(ostream &out,ostream *out_h) {
Functions::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi);
@ -64,7 +64,7 @@ write_prototypes(ostream &out) {
}
out << "\n";
InterfaceMakerPython::write_prototypes(out);
InterfaceMakerPython::write_prototypes(out,out_h);
}
////////////////////////////////////////////////////////////////////
@ -92,8 +92,8 @@ write_functions(ostream &out) {
// support a module file.
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonSimple::
write_module(ostream &out, InterrogateModuleDef *def) {
InterfaceMakerPython::write_module(out, def);
write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
InterfaceMakerPython::write_module(out,out_h, def);
out << "static PyMethodDef python_simple_funcs[] = {\n";
@ -215,8 +215,7 @@ write_function_for(ostream &out, InterfaceMaker::Function *func) {
// Description: Writes out the particular function that handles a
// single instance of an overloaded function.
////////////////////////////////////////////////////////////////////
void InterfaceMakerPythonSimple::
write_function_instance(ostream &out, InterfaceMaker::Function *func,
void InterfaceMakerPythonSimple::write_function_instance(ostream &out, InterfaceMaker::Function *func,
FunctionRemap *remap) {
out << "/*\n"
<< " * Python simple wrapper for\n"
@ -435,7 +434,8 @@ pack_return_value(ostream &out, int indent_level,
CPPType *orig_type = remap->_return_type->get_orig_type();
CPPType *type = remap->_return_type->get_new_type();
if (remap->_return_type->new_type_is_atomic_string()) {
if (remap->_return_type->new_type_is_atomic_string())
{
if (TypeManager::is_char_pointer(orig_type)) {
indent(out, indent_level)
<< "return PyString_FromString(" << return_expr << ");\n";
@ -446,11 +446,13 @@ pack_return_value(ostream &out, int indent_level,
<< return_expr << ".data(), " << return_expr << ".length());\n";
}
} else if (TypeManager::is_unsigned_longlong(type)) {
} else if (TypeManager::is_unsigned_longlong(type))
{
indent(out, indent_level)
<< "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
} else if (TypeManager::is_longlong(type)) {
} else if (TypeManager::is_longlong(type))
{
indent(out, indent_level)
<< "return PyLong_FromLongLong(" << return_expr << ");\n";

View File

@ -43,10 +43,10 @@ public:
InterfaceMakerPythonSimple(InterrogateModuleDef *def);
virtual ~InterfaceMakerPythonSimple();
virtual void write_prototypes(ostream &out);
virtual void write_prototypes(ostream &out,ostream *out_h);
virtual void write_functions(ostream &out);
virtual void write_module(ostream &out, InterrogateModuleDef *def);
virtual void write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def);
virtual bool synthesize_this_parameter();

View File

@ -37,6 +37,7 @@
CPPParser parser;
Filename output_code_filename;
Filename output_include_filename;
Filename output_data_filename;
string output_data_basename;
bool output_module_specific = false;
@ -49,11 +50,12 @@ bool true_wrapper_names = false;
bool build_c_wrappers = false;
bool build_python_wrappers = false;
bool build_python_obj_wrappers = false;
bool build_python_native = false;
bool track_interpreter = false;
bool save_unique_names = false;
bool no_database = false;
bool generate_spam = false;
bool left_inheritance_requires_upcast = false;
bool left_inheritance_requires_upcast = true;
CPPVisibility min_vis = V_published;
string library_name;
string module_name;
@ -77,6 +79,7 @@ enum CommandOptions {
CO_c,
CO_python,
CO_python_obj,
CO_python_native,
CO_track_interpreter,
CO_unique_names,
CO_nodb,
@ -101,6 +104,7 @@ static struct option long_options[] = {
{ "c", no_argument, NULL, CO_c },
{ "python", no_argument, NULL, CO_python },
{ "python-obj", no_argument, NULL, CO_python_obj },
{ "python-native", no_argument, NULL, CO_python_native },
{ "track-interpreter", no_argument, NULL, CO_track_interpreter },
{ "unique-names", no_argument, NULL, CO_unique_names },
{ "nodb", no_argument, NULL, CO_nodb },
@ -241,6 +245,10 @@ void show_help() {
<< " Generate Python function wrappers that convert C++ objects to true\n"
<< " python objects, with all methods converted to Python methods. This\n"
<< " is currently experimental.\n\n"
<< " -python-native\n"
<< " Generate Python function wrappers that convert C++ objects to true\n"
<< " python objects, with all methods converted to Python methods. This\n"
<< " is currently experimental.\n\n"
<< " Any combination of -c, -python, or -python-obj may be specified. If all\n"
<< " are omitted, the default is -c.\n\n"
@ -278,15 +286,15 @@ void show_help() {
// handle commandline -D options
static void
predefine_macro(CPPParser& parser, const string& option) {
predefine_macro(CPPParser& parser, const string& inoption) {
string macro_name, macro_def;
size_t eq = option.find('=');
size_t eq = inoption.find('=');
if (eq != string::npos) {
macro_name = option.substr(0, eq);
macro_def = option.substr(eq + 1);
macro_name = inoption.substr(0, eq);
macro_def = inoption.substr(eq + 1);
} else {
macro_name = option;
macro_name = inoption;
}
CPPManifest *macro = new CPPManifest(macro_name + " " + macro_def);
@ -384,6 +392,10 @@ main(int argc, char *argv[]) {
build_python_obj_wrappers = true;
break;
case CO_python_native:
build_python_native = true;
break;
case CO_track_interpreter:
track_interpreter = true;
break;
@ -427,8 +439,16 @@ main(int argc, char *argv[]) {
exit(1);
}
// if(!output_code_filename.empty())
// {
// output_include_filename = output_code_filename.get_fullpath_wo_extension() +".h";
// printf(" Include File Will be Set to %s \n",output_include_filename.c_str());
// }
output_code_filename.set_text();
output_data_filename.set_text();
// output_include_filename.set_text();
output_data_basename = output_data_filename.get_basename();
if (output_function_names && true_wrapper_names) {
@ -440,14 +460,16 @@ main(int argc, char *argv[]) {
}
if (!build_c_wrappers && !build_python_wrappers &&
!build_python_obj_wrappers) {
!build_python_obj_wrappers &&!build_python_native) {
build_c_wrappers = true;
}
// Get all of the .h files.
for (i = 1; i < argc; ++i) {
for (i = 1; i < argc; ++i)
{
Filename filename = Filename::from_os_specific(argv[i]);
if (!parser.parse_file(Filename::from_os_specific(filename))) {
if (!parser.parse_file(Filename::from_os_specific(filename)))
{
cerr << "Error parsing file: '" << argv[i] << "'\n";
exit(1);
}
@ -479,9 +501,37 @@ main(int argc, char *argv[]) {
// database, so we can check synchronicity at load time.
int file_identifier = time((time_t *)NULL);
InterrogateModuleDef *def = builder.make_module_def(file_identifier);
ofstream * the_output_include = NULL;
ofstream output_include;
if (1==2 && !output_include_filename.empty())
{
output_include_filename.open_write(output_include);
output_include << "#ifndef " << output_include_filename.get_basename_wo_extension() << "__HH__\n";
output_include << "#define " << output_include_filename.get_basename_wo_extension() << "__HH__\n";
output_include
<< "/*\n"
<< " * This file generated by:\n"
<< " * " << command_line << "\n"
<< " *\n"
<< " */\n\n";
if (output_include.fail())
{
nout << "Unable to write to " << output_include_filename << "\n";
exit(-1);
}
the_output_include = &output_include;
}
// Now output all of the wrapper functions.
if (!output_code_filename.empty()) {
if (!output_code_filename.empty())
{
ofstream output_code;
output_code_filename.open_write(output_code);
@ -492,19 +542,30 @@ main(int argc, char *argv[]) {
<< " *\n"
<< " */\n\n";
if(the_output_include != NULL)
{
output_code << "#include \""<<output_include_filename<<"\"\n";
*the_output_include << "#include \"" << output_include_filename.get_fullpath_wo_extension() << "_pynative.h\"\n";
}
if (output_code.fail()) {
nout << "Unable to write to " << output_code_filename << "\n";
} else {
builder.write_code(output_code, def);
builder.write_code(output_code,the_output_include, def);
}
}
if(the_output_include != NULL)
*the_output_include << "#endif // #define " << output_include_filename.get_basename_wo_extension() << "__HH__\n";
// And now output the bulk of the database.
if (!output_data_filename.empty()) {
ofstream output_data;
output_data_filename.open_write(output_data);
if (output_data.fail()) {
if (output_data.fail())
{
nout << "Unable to write to " << output_data_filename << "\n";
} else {
InterrogateDatabase::get_ptr()->write(output_data, def);

View File

@ -41,6 +41,7 @@ extern bool true_wrapper_names;
extern bool build_c_wrappers;
extern bool build_python_wrappers;
extern bool build_python_obj_wrappers;
extern bool build_python_native;
extern bool track_interpreter;
extern bool save_unique_names;
extern bool no_database;

View File

@ -24,6 +24,7 @@
#include "interfaceMakerC.h"
#include "interfaceMakerPythonObj.h"
#include "interfaceMakerPythonSimple.h"
#include "interfaceMakerPythonNative.h"
#include "functionRemap.h"
#include "interrogateType.h"
@ -53,19 +54,8 @@
#include <algorithm>
InterrogateBuilder builder;
/*
static string
upcase_string(const string &str) {
string result;
for (string::const_iterator si = str.begin();
si != str.end();
++si) {
result += toupper(*si);
}
return result;
}
*/
std::string EXPORT_IMPORT_PREFEX;
bool inside_python_native = false;
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::add_source_file
@ -238,18 +228,24 @@ build() {
for (di = parser._declarations.begin();
di != parser._declarations.end();
++di) {
if ((*di)->get_subtype() == CPPDeclaration::ST_instance) {
if ((*di)->get_subtype() == CPPDeclaration::ST_instance)
{
CPPInstance *inst = (*di)->as_instance();
if (inst->_type->get_subtype() == CPPDeclaration::ST_function) {
if (inst->_type->get_subtype() == CPPDeclaration::ST_function)
{
// Here's a function declaration.
scan_function(inst);
} else {
}
else
{
// Here's a data element declaration.
scan_element(inst, (CPPStructType *)NULL, &parser);
}
} else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) {
}
else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef)
{
CPPTypedef *tdef = (*di)->as_typedef();
if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) {
// A typedef counts as a declaration. This lets us pick up
@ -263,9 +259,9 @@ build() {
CPPType *type = (*di)->as_type_declaration()->_type;
type->_vis = (*di)->_vis;
if (type->get_subtype() == CPPDeclaration::ST_struct) {
CPPStructType *struct_type =
type->as_type()->resolve_type(&parser, &parser)->as_struct_type();
if (type->get_subtype() == CPPDeclaration::ST_struct)
{
CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type();
scan_struct_type(struct_type);
} else if (type->get_subtype() == CPPDeclaration::ST_enum) {
@ -293,8 +289,7 @@ build() {
// Description: Generates all the code necessary to the indicated
// output stream.
////////////////////////////////////////////////////////////////////
void InterrogateBuilder::
write_code(ostream &out, InterrogateModuleDef *def) {
void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, InterrogateModuleDef *def) {
typedef vector<InterfaceMaker *> InterfaceMakers;
InterfaceMakers makers;
@ -313,8 +308,18 @@ write_code(ostream &out, InterrogateModuleDef *def) {
makers.push_back(maker);
}
InterfaceMakers::iterator mi;
if (build_python_native ) {
InterfaceMakerPythonNative *maker = new InterfaceMakerPythonNative(def);
makers.push_back(maker);
}
EXPORT_IMPORT_PREFEX = std::string("EXPCL_") + def->module_name;
for (size_t i=0; i<EXPORT_IMPORT_PREFEX.size(); i++)
EXPORT_IMPORT_PREFEX[i] = toupper(EXPORT_IMPORT_PREFEX[i]);
InterfaceMakers::iterator mi;
// First, make all the wrappers.
for (mi = makers.begin(); mi != makers.end(); ++mi) {
(*mi)->generate_wrappers();
@ -330,15 +335,25 @@ write_code(ostream &out, InterrogateModuleDef *def) {
}
// Now, begin the actual output. Start with the #include lines.
if (!no_database) {
out << "#include \"dtoolbase.h\"\n"
if (!no_database)
{
out_code << "#include \"dtoolbase.h\"\n"
<< "#include \"interrogate_request.h\"\n"
<< "#include \"dconfig.h\"\n";
}
ostringstream declaration_bodies;
if (watch_asserts) {
out << "#include \"notify.h\"\n";
declaration_bodies << "#include \"notify.h\"\n";
}
out << "\n";
declaration_bodies << "#include <sstream>\n";
declaration_bodies << "#include \"py_panda.h\" \n";
declaration_bodies << "\n";
IncludeFiles::const_iterator ifi;
for (ifi = _include_files.begin();
@ -348,41 +363,54 @@ write_code(ostream &out, InterrogateModuleDef *def) {
char delimiter = (*ifi).second;
if (should_include(filename)) {
if (delimiter == '"') {
out << "#include \"" << filename << "\"\n";
declaration_bodies << "#include \"" << filename << "\"\n";
} else {
out << "#include <" << filename << ">\n";
declaration_bodies << "#include <" << filename << ">\n";
}
}
}
out << "\n";
declaration_bodies << "\n";
for (mi = makers.begin(); mi != makers.end(); ++mi) {
(*mi)->write_includes(out);
(*mi)->write_includes(declaration_bodies);
}
if (generate_spam) {
out << "#include \"config_interrogatedb.h\"\n"
declaration_bodies << "#include \"config_interrogatedb.h\"\n"
<< "#include \"notifyCategoryProxy.h\"\n\n"
<< "NotifyCategoryDeclNoExport(in_" << library_name << ");\n"
<< "NotifyCategoryDef(in_" << library_name << ", interrogatedb_cat);\n\n";
}
out << "\n";
declaration_bodies << "\n";
// And now the prototypes.
for (mi = makers.begin(); mi != makers.end(); ++mi) {
(*mi)->write_prototypes(out);
(*mi)->write_prototypes(declaration_bodies,out_include);
}
declaration_bodies << "\n";
// if(out_include != NULL)
// (*out_include) << declaration_bodies.str();
// else
out_code << declaration_bodies.str();
out << "\n";
// Followed by the function bodies.
out << function_bodies.str() << "\n";
out_code << function_bodies.str() << "\n";
for (mi = makers.begin(); mi != makers.end(); ++mi) {
(*mi)->write_module_support(out_code,out_include,def);
}
if (output_module_specific) {
// Output whatever stuff we should output if this were a module.
for (mi = makers.begin(); mi != makers.end(); ++mi) {
(*mi)->write_module(out, def);
(*mi)->write_module(out_code,out_include, def);
}
}
@ -410,7 +438,7 @@ write_code(ostream &out, InterrogateModuleDef *def) {
if (output_function_pointers) {
// Write out the table of function pointers.
out << "static void *_in_fptrs[" << num_wrappers << "] = {\n";
out_code << "static void *_in_fptrs[" << num_wrappers << "] = {\n";
int next_index = 1;
map<int, FunctionRemap *>::iterator ii;
for (ii = wrappers_by_index.begin();
@ -418,79 +446,84 @@ write_code(ostream &out, InterrogateModuleDef *def) {
++ii) {
int this_index = (*ii).first;
while (next_index < this_index) {
out << " (void *)0,\n";
out_code << " (void *)0,\n";
next_index++;
}
assert(next_index == this_index);
FunctionRemap *remap = (*ii).second;
out << " (void *)&" << remap->_wrapper_name << ",\n";
out_code << " (void *)&" << remap->_wrapper_name << ",\n";
next_index++;
}
while (next_index < num_wrappers + 1) {
out << " (void *)0,\n";
out_code << " (void *)0,\n";
next_index++;
}
out << "};\n\n";
out_code << "};\n\n";
}
if (save_unique_names) {
// Write out the table of unique names, in no particular order.
out << "static InterrogateUniqueNameDef _in_unique_names["
out_code << "static InterrogateUniqueNameDef _in_unique_names["
<< num_wrappers << "] = {\n";
for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
FunctionRemap *remap = (*ri);
out << " { \""
out_code << " { \""
<< remap->_unique_name << "\", "
<< remap->_wrapper_index - 1 << " },\n";
}
out << "};\n\n";
out_code << "};\n\n";
}
//if(1==2)
{
if (!no_database) {
// Now build the module definition structure to add ourselves to
// the global interrogate database.
out << "static InterrogateModuleDef _in_module_def = {\n"
out_code << "static InterrogateModuleDef _in_module_def = {\n"
<< " " << def->file_identifier << ", /* file_identifier */\n"
<< " \"" << def->library_name << "\", /* library_name */\n"
<< " \"" << def->library_hash_name << "\", /* library_hash_name */\n"
<< " \"" << def->module_name << "\", /* module_name */\n";
if (def->database_filename != (const char *)NULL) {
out << " \"" << def->database_filename
out_code << " \"" << def->database_filename
<< "\", /* database_filename */\n";
} else {
out << " (const char *)0, /* database_filename */\n";
out_code << " (const char *)0, /* database_filename */\n";
}
if (save_unique_names) {
out << " _in_unique_names,\n"
out_code << " _in_unique_names,\n"
<< " " << num_wrappers << ", /* num_unique_names */\n";
} else {
out << " (InterrogateUniqueNameDef *)0, /* unique_names */\n"
out_code << " (InterrogateUniqueNameDef *)0, /* unique_names */\n"
<< " 0, /* num_unique_names */\n";
}
if (output_function_pointers) {
out << " _in_fptrs,\n"
if (output_function_pointers) {
out_code << " _in_fptrs,\n"
<< " " << num_wrappers << ", /* num_fptrs */\n";
} else {
out << " (void **)0, /* fptrs */\n"
out_code << " (void **)0, /* fptrs */\n"
<< " 0, /* num_fptrs */\n";
}
out << " 1, /* first_index */\n"
out_code << " 1, /* first_index */\n"
<< " " << InterrogateDatabase::get_ptr()->get_next_index()
<< " /* next_index */\n"
<< "};\n\n";
// And now write the static-init code that tells the interrogate
// database to load up this module.
out << "Configure(_in_configure_" << library_name << ");\n"
out_code << "Configure(_in_configure_" << library_name << ");\n"
<< "ConfigureFn(_in_configure_" << library_name << ") {\n"
<< " interrogate_request_module(&_in_module_def);\n"
<< "}\n\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: InterrogateBuilder::make_module_def
@ -938,10 +971,9 @@ scan_function(CPPFunctionGroup *fgroup) {
void InterrogateBuilder::
scan_function(CPPInstance *function) {
assert(function != (CPPInstance *)NULL);
assert(function->_type != (CPPType *)NULL &&
function->_type->as_function_type() != (CPPFunctionType *)NULL);
CPPFunctionType *ftype =
function->_type->resolve_type(&parser, &parser)->as_function_type();
assert(function->_type != (CPPType *)NULL && function->_type->as_function_type() != (CPPFunctionType *)NULL);
CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type();
assert(ftype != (CPPFunctionType *)NULL);
CPPScope *scope = &parser;
@ -1040,7 +1072,8 @@ scan_struct_type(CPPStructType *type) {
// Check if any of the members are exported. If none of them are,
// and the type itself is not marked for export, then never mind.
if (type->_vis > min_vis) {
if (type->_vis > min_vis)
{
CPPScope *scope = type->_scope;
bool any_exported = false;
@ -1713,7 +1746,8 @@ get_type(CPPType *type, bool global) {
// If it's an extension type of some kind, it might be scoped.
if (ext_type->_ident != (CPPIdentifier *)NULL) {
CPPScope *scope = ext_type->_ident->get_scope(&parser, &parser);
while (scope->as_template_scope() != (CPPTemplateScope *)NULL) {
while (scope->as_template_scope() != (CPPTemplateScope *)NULL)
{
assert(scope->get_parent_scope() != scope);
scope = scope->get_parent_scope();
assert(scope != (CPPScope *)NULL);
@ -1734,19 +1768,23 @@ get_type(CPPType *type, bool global) {
}
}
if (forced || !in_ignoretype(true_name)) {
if (forced || !in_ignoretype(true_name))
{
itype._flags |= InterrogateType::F_fully_defined;
if (type->as_simple_type() != (CPPSimpleType *)NULL) {
if (type->as_simple_type() != (CPPSimpleType *)NULL)
{
define_atomic_type(itype, type->as_simple_type());
} else if (type->as_pointer_type() != (CPPPointerType *)NULL) {
} else if (type->as_pointer_type() != (CPPPointerType *)NULL)
{
define_wrapped_type(itype, type->as_pointer_type());
} else if (type->as_const_type() != (CPPConstType *)NULL) {
define_wrapped_type(itype, type->as_const_type());
} else if (type->as_struct_type() != (CPPStructType *)NULL) {
} else if (type->as_struct_type() != (CPPStructType *)NULL)
{
define_struct_type(itype, type->as_struct_type(), index, forced);
} else if (type->as_enum_type() != (CPPEnumType *)NULL) {
@ -1930,9 +1968,12 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
bi != cpptype->_derivation.end();
++bi) {
const CPPStructType::Base &base = (*bi);
if (base._vis <= V_public) {
if (base._vis <= V_public)
{
CPPType *base_type = TypeManager::resolve_type(base._base, scope);
TypeIndex base_index = get_type(base_type, true);
if (base_index == 0) {
nout << *cpptype << " reports a derivation from an invalid type.\n";
@ -1946,6 +1987,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
// Do we need to synthesize upcast and downcast functions?
bool generate_casts = false;
// Function To Generate all castsss Posible..
if (base._is_virtual) {
// We do in the presence of virtual inheritance.
generate_casts = true;
@ -1972,6 +2015,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
}
if (generate_casts) {
d._upcast = get_cast_function(base_type, cpptype, "upcast");
d._flags |= InterrogateType::DF_upcast;
@ -2008,12 +2053,15 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
}
}
} else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) {
} else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration)
{
CPPType *type = (*di)->as_type_declaration()->_type;
if ((*di)->_vis <= min_vis) {
if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser)))
{
if (type->as_struct_type() != (CPPStructType *)NULL ||
type->as_enum_type() != (CPPEnumType *)NULL) {
type->as_enum_type() != (CPPEnumType *)NULL)
{
// Here's a nested class or enum definition.
type->_vis = (*di)->_vis;
@ -2021,7 +2069,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
assert(nested_type != (CPPExtensionType *)NULL);
// Only try to export named types.
if (nested_type->_ident != (CPPIdentifier *)NULL) {
if (nested_type->_ident != (CPPIdentifier *)NULL)
{
TypeIndex nested_index = get_type(nested_type, false);
itype._nested_types.push_back(nested_index);
}
@ -2129,7 +2178,8 @@ void InterrogateBuilder::
define_method(CPPFunctionGroup *fgroup, InterrogateType &itype,
CPPStructType *struct_type, CPPScope *scope) {
CPPFunctionGroup::Instances::const_iterator fi;
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi)
{
CPPInstance *function = (*fi);
define_method(function, itype, struct_type, scope);
}

View File

@ -59,7 +59,7 @@ public:
void read_command_file(istream &in);
void do_command(const string &command, const string &params);
void build();
void write_code(ostream &out, InterrogateModuleDef *def);
void write_code(ostream &out_code,ostream *out_include, InterrogateModuleDef *def);
InterrogateModuleDef *make_module_def(int file_identifier);
static string clean_identifier(const string &name);
@ -68,8 +68,10 @@ public:
string get_preferred_name(CPPType *type);
static string hash_string(const string &name, int shift_offset);
TypeIndex get_type(CPPType *type, bool global);
private:
public:
typedef set<string> Commands;
typedef map<string, string> CommandParams;
void insert_param_list(InterrogateBuilder::Commands &commands,
@ -108,7 +110,7 @@ private:
int flags, const string &expression = string());
TypeIndex get_atomic_string_type();
TypeIndex get_type(CPPType *type, bool global);
// TypeIndex get_type(CPPType *type, bool global);
void define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype);
void define_wrapped_type(InterrogateType &itype, CPPPointerType *cpptype);

View File

@ -8,6 +8,7 @@
#include "interfaceMaker.cxx"
#include "interfaceMakerC.cxx"
#include "interfaceMakerPython.cxx"
#include "interfaceMakerPythonNative.cxx"
#include "interfaceMakerPythonObj.cxx"
#include "interfaceMakerPythonSimple.cxx"

View File

@ -27,6 +27,8 @@
#include "pystub.h"
#include "notify.h"
#include "set"
// If our system getopt() doesn't come with getopt_long_only(), then use
// the GNU flavor that we've got in tool for this purpose.
#ifndef HAVE_GETOPT_LONG_ONLY
@ -40,6 +42,7 @@ string module_name;
string library_name;
bool build_c_wrappers = false;
bool build_python_wrappers = false;
bool build_python_native_wrappers = false;
bool track_interpreter = false;
// Short command-line options.
@ -52,6 +55,7 @@ enum CommandOptions {
CO_library,
CO_c,
CO_python,
CO_python_native,
CO_track_interpreter,
};
@ -61,6 +65,7 @@ static struct option long_options[] = {
{ "library", required_argument, NULL, CO_library },
{ "c", no_argument, NULL, CO_c },
{ "python", no_argument, NULL, CO_python },
{ "python-native", no_argument, NULL, CO_python_native },
{ "track-interpreter", no_argument, NULL, CO_track_interpreter },
{ NULL }
};
@ -78,8 +83,88 @@ upcase_string(const string &str) {
}
*/
int
write_python_table(ostream &out) {
int write_python_table_native(ostream &out)
{
out << "\n#include \"dtoolbase.h\"\n"
<< "#include \"interrogate_request.h\"\n\n"
<< "#undef _POSIX_C_SOURCE\n"
<< "#include \"py_panda.h\"\n\n";
int count = 0;
std::set<std::string > Libraries;
// out << "extern \"C\" {\n";
// Walk through all of the Python functions.
int num_functions = interrogate_number_of_functions();
int fi;
for (fi = 0; fi < num_functions; fi++)
{
FunctionIndex function_index = interrogate_get_function(fi);
// Consider only those that belong in the module we asked for.
if (interrogate_function_has_module_name(function_index) &&
module_name == interrogate_function_module_name(function_index))
{
// if it has a library name add it to set of libraries
if(interrogate_function_has_library_name(function_index))
Libraries.insert(interrogate_function_library_name(function_index));
}
}
for(int ti = 0; ti < interrogate_number_of_types(); ti++)
{
TypeIndex thetype = interrogate_get_type(ti);
if(interrogate_type_has_module_name(thetype) && module_name == interrogate_type_module_name(thetype))
{
if(interrogate_type_has_library_name(thetype))
Libraries.insert(interrogate_type_library_name(thetype));
}
}
std::set<std::string >::iterator ii;
for(ii = Libraries.begin(); ii != Libraries.end(); ii++)
{
printf("Referencing Library %s\n",(*ii).c_str());
out << "extern LibrayDef "<< *ii << "_moddef ;\n";
}
out << "#ifdef _WIN32\n"
<< "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
<< "#else\n"
<< "extern \"C\" void init" << library_name << "();\n"
<< "#endif\n\n"
<< "void init" << library_name << "() \n{\n";
if (track_interpreter) {
out << " in_interpreter = 1;\n";
}
out << " LibrayDef *defs[] = {";
for(ii = Libraries.begin(); ii != Libraries.end(); ii++)
out << "&"<< *ii << "_moddef,";
out << " NULL };\n ";
out << " Dtool_PyModuleInitHelper( defs, \"" << library_name << "\");\n";
out << "\n\n\n}\n";
return count;
}
int write_python_table(ostream &out)
{
out << "\n#include \"dtoolbase.h\"\n"
<< "#include \"interrogate_request.h\"\n\n"
<< "#undef _POSIX_C_SOURCE\n"
@ -175,8 +260,8 @@ write_python_table(ostream &out) {
return count;
}
int
main(int argc, char *argv[]) {
int main(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
int flag;
@ -204,6 +289,10 @@ main(int argc, char *argv[]) {
build_python_wrappers = true;
break;
case CO_python_native:
build_python_native_wrappers = true;
break;
case CO_track_interpreter:
track_interpreter = true;
break;
@ -226,7 +315,7 @@ main(int argc, char *argv[]) {
output_code_filename.set_text();
if (!build_c_wrappers && !build_python_wrappers) {
if (!build_c_wrappers && !build_python_wrappers && !build_python_native_wrappers) {
build_c_wrappers = true;
}
@ -253,16 +342,24 @@ main(int argc, char *argv[]) {
}
// Now output the table.
if (!output_code_filename.empty()) {
if (!output_code_filename.empty())
{
ofstream output_code;
if (!output_code_filename.open_write(output_code)) {
if (!output_code_filename.open_write(output_code))
{
nout << "Unable to write to " << output_code_filename << "\n";
} else {
if (build_python_wrappers) {
int count = write_python_table(output_code);
nout << count << " python function wrappers exported.\n";
}
if (build_python_native_wrappers) {
write_python_table_native(output_code);
}
}
}

View File

@ -54,7 +54,7 @@ pass_parameter(ostream &out, const string &variable_name) {
string ParameterRemapBasicStringToString::
prepare_return_expr(ostream &out, int indent_level, const string &expression) {
InterfaceMaker::indent(out, indent_level)
<< "static basic_string<char> string_holder = " << expression << ";\n";
<< "static string string_holder = " << expression << ";\n";
return "string_holder";
}

View File

@ -29,6 +29,9 @@
#include "cppStructType.h"
#include "cppTypeDeclaration.h"
#include "notify.h"
#include "cppTypedef.h"
#include "cppEnumType.h"
////////////////////////////////////////////////////////////////////
// Function: TypeManager::resolve_type
@ -818,6 +821,47 @@ is_PyObject(CPPType *type) {
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_ostream
// Access: Public, Static
// Description: Returns true if the indicated type is PyObject.
////////////////////////////////////////////////////////////////////
bool TypeManager::is_ostream(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_ostream(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_struct:
return (type->get_local_name(&parser) == "ostream");
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_pointer_to_PyObject
// Access: Public, Static
// Description: Returns true if the indicated type is PyObject *.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_pointer_to_ostream(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_pointer_to_ostream(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_reference:
return is_ostream(type->as_reference_type()->_pointing_at);
case CPPDeclaration::ST_pointer:
return is_ostream(type->as_pointer_type()->_pointing_at);
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::involves_unpublished
// Access: Public, Static
@ -1313,3 +1357,171 @@ has_protected_destructor(CPPType *type) {
// No explicit destructor.
return false;
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::has_protected_destructor
// Access: Public, Static
// Description: Returns true if the destructor for the given class or
// struct is protected or private, or false if the
// destructor is public or absent.
////////////////////////////////////////////////////////////////////
bool TypeManager::IsExported(CPPType *in_type)
{
string name = in_type->get_local_name(&parser);
if (name.empty()) {
return false;
}
//return true;
// this question is about the base type
CPPType *base_type = resolve_type(unwrap(in_type));
//CPPType *base_type = in_type;
// Ok export Rules..
// Classes and Structs and Unions are exported only if they have a
// function that is exported..
// function is the easiest case.
if (base_type->_vis <= min_vis)
return true;
if (in_type->_vis <= min_vis)
return true;
if (base_type->get_subtype() == CPPDeclaration::ST_struct)
{
CPPStructType *sstruct_type = base_type->as_struct_type();
CPPStructType *struct_type =sstruct_type->resolve_type(&parser, &parser)->as_struct_type();
CPPScope *scope = struct_type->_scope;
CPPScope::Declarations::const_iterator di;
for (di = scope->_declarations.begin();di != scope->_declarations.end(); di++)
if ((*di)->_vis <= min_vis)
return true;
}
else if (base_type->get_subtype() == CPPDeclaration::ST_instance)
{
CPPInstance *inst = base_type->as_instance();
if (inst->_type->get_subtype() == CPPDeclaration::ST_function)
{
CPPInstance *function = inst;
CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type();
if (ftype->_vis <= min_vis)
return true;
}
else
{
if (inst->_vis <= min_vis)
return true;
}
}
else if (base_type->get_subtype() == CPPDeclaration::ST_typedef)
{
CPPTypedef *tdef = base_type->as_typedef();
if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct)
{
CPPStructType *struct_type =tdef->_type->resolve_type(&parser, &parser)->as_struct_type();
return IsExported(struct_type);
}
}
else if (base_type->get_subtype() == CPPDeclaration::ST_type_declaration)
{
CPPType *type = base_type->as_type_declaration()->_type;
if (type->get_subtype() == CPPDeclaration::ST_struct)
{
CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type();
CPPScope *scope = struct_type->_scope;
return IsExported(struct_type);
}
else if (type->get_subtype() == CPPDeclaration::ST_enum)
{
CPPEnumType *enum_type = type->as_type()->resolve_type(&parser, &parser)->as_enum_type();
if (type->_vis <= min_vis)
return true;
}
}
// printf("---------------------> Visibility Failed %s %d Vis=%d, Minvis=%d\n",
// base_type->get_fully_scoped_name().c_str(),
// base_type->get_subtype(),
// base_type->_vis,
// min_vis);
return false;
};
bool TypeManager::IsLocal(CPPType *in_type)
{
// A local means it was compiled in this scope of work..
// IE a should actualy generate code for this objects....
CPPType *base_type = resolve_type(unwrap(in_type));
if(base_type->_file._source == CPPFile::S_local)
return true;
return false;
if (base_type->get_subtype() == CPPDeclaration::ST_struct)
{
CPPStructType *struct_type = base_type->as_struct_type();
if (struct_type->_file._source == CPPFile::S_local)
return true;
}
else if (base_type->get_subtype() == CPPDeclaration::ST_instance)
{
CPPInstance *inst = base_type->as_instance();
if (inst->_type->get_subtype() == CPPDeclaration::ST_function)
{
CPPInstance *function = inst;
CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type();
if (ftype->_file._source == CPPFile::S_local)
return true;
}
else
{
if (inst->_file._source == CPPFile::S_local)
return true;
}
}
else if (base_type->get_subtype() == CPPDeclaration::ST_typedef)
{
CPPTypedef *tdef = base_type->as_typedef();
if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct)
{
CPPStructType *struct_type =tdef->_type->resolve_type(&parser, &parser)->as_struct_type();
return IsLocal(struct_type);
}
}
else if (base_type->get_subtype() == CPPDeclaration::ST_type_declaration)
{
CPPType *type = base_type->as_type_declaration()->_type;
if (type->get_subtype() == CPPDeclaration::ST_struct)
{
CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type();
if (struct_type->_file._source == CPPFile::S_local)
return true;
}
else if (type->get_subtype() == CPPDeclaration::ST_enum)
{
CPPEnumType *enum_type = type->as_type()->resolve_type(&parser, &parser)->as_enum_type();
if (enum_type->_file._source != CPPFile::S_local)
return true;
}
}
if (base_type->_file._source == CPPFile::S_local)
return true;
return false;
};

View File

@ -84,6 +84,9 @@ public:
static bool involves_unpublished(CPPType *type);
static bool involves_protected(CPPType *type);
static bool is_ostream(CPPType *type);
static bool is_pointer_to_ostream(CPPType *type);
static CPPType *unwrap_pointer(CPPType *type);
static CPPType *unwrap_reference(CPPType *type);
static CPPType *unwrap_const(CPPType *type);
@ -107,6 +110,11 @@ public:
static string get_function_name(CPPInstance *function);
static bool has_protected_destructor(CPPType *type);
static bool IsExported(CPPType *type);
static bool IsLocal(CPPType *type);
};
#endif

View File

@ -27,6 +27,6 @@
#define INSTALL_HEADERS \
interrogate_interface.h interrogate_request.h vector_int.h \
config_interrogatedb.h
config_interrogatedb.h py_panda.h
#end lib_target

View File

@ -5,7 +5,7 @@
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
//O
// 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

View File

@ -101,6 +101,7 @@ public:
friend class InterrogateBuilder;
friend class InterfaceMakerC;
friend class InterfaceMakerPythonSimple;
friend class InterfaceMakerPythonNative;
friend class FunctionRemap;
};

View File

@ -224,3 +224,17 @@ remap_indices(const IndexRemapper &remap) {
}
}
EXPCL_DTOOLCONFIG RunTimeTypeDictionary & GetRunTimeDictionary()
{
static RunTimeTypeDictionary dict;
return dict;
};
EXPCL_DTOOLCONFIG RunTimeTypeList & GetRunTimeTypeList()
{
static RunTimeTypeList list;
return list;
};

View File

@ -135,7 +135,9 @@ private:
F_unpublished = 0x100000,
};
public:
int _flags;
string _scoped_name;
string _true_name;
string _comment;
@ -221,4 +223,14 @@ INLINE istream &operator >> (istream &in, InterrogateType::EnumValue &d);
#include "interrogateType.I"
#include <set>
#include <map>
struct Dtool_PyTypedObject;
typedef std::map< int , Dtool_PyTypedObject *> RunTimeTypeDictionary;
typedef std::set<int > RunTimeTypeList;
extern "C" EXPCL_DTOOL RunTimeTypeDictionary & GetRunTimeDictionary();
extern "C" EXPCL_DTOOL RunTimeTypeList & GetRunTimeTypeList();
#endif

View File

@ -217,6 +217,18 @@ interrogate_function_module_name(FunctionIndex function) {
return InterrogateDatabase::get_ptr()->get_function(function).get_module_name();
}
bool
interrogate_function_has_library_name(FunctionIndex function) {
return InterrogateDatabase::get_ptr()->get_function(function).has_library_name();
}
const char *
interrogate_function_library_name(FunctionIndex function) {
return InterrogateDatabase::get_ptr()->get_function(function).get_library_name();
}
bool
interrogate_function_is_virtual(FunctionIndex function) {
return InterrogateDatabase::get_ptr()->get_function(function).is_virtual();
@ -401,6 +413,17 @@ interrogate_type_module_name(TypeIndex type) {
return InterrogateDatabase::get_ptr()->get_type(type).get_module_name();
}
bool
interrogate_type_has_library_name(TypeIndex type) {
return InterrogateDatabase::get_ptr()->get_type(type).has_library_name();
}
const char *
interrogate_type_library_name(TypeIndex type) {
return InterrogateDatabase::get_ptr()->get_type(type).get_library_name();
}
bool
interrogate_type_is_atomic(TypeIndex type) {
return InterrogateDatabase::get_ptr()->get_type(type).is_atomic();

View File

@ -229,6 +229,11 @@ EXPCL_DTOOLCONFIG TypeIndex interrogate_function_class(FunctionIndex function);
EXPCL_DTOOLCONFIG bool interrogate_function_has_module_name(FunctionIndex function);
EXPCL_DTOOLCONFIG const char *interrogate_function_module_name(FunctionIndex function);
// This returns the library name reported for the function, if
// available.
EXPCL_DTOOLCONFIG bool interrogate_function_has_library_name(FunctionIndex function);
EXPCL_DTOOLCONFIG const char *interrogate_function_library_name(FunctionIndex function);
// This is true for virtual member functions. It's not likely that
// this will be important to the scripting language.
EXPCL_DTOOLCONFIG bool interrogate_function_is_virtual(FunctionIndex function);
@ -388,6 +393,11 @@ EXPCL_DTOOLCONFIG const char *interrogate_type_comment(TypeIndex type);
EXPCL_DTOOLCONFIG bool interrogate_type_has_module_name(TypeIndex type);
EXPCL_DTOOLCONFIG const char *interrogate_type_module_name(TypeIndex type);
// This returns the library name reported for the type, if available.
EXPCL_DTOOLCONFIG bool interrogate_type_has_library_name(TypeIndex type);
EXPCL_DTOOLCONFIG const char *interrogate_type_library_name(TypeIndex type);
// If interrogate_type_is_atomic() returns true, the type is one of
// the basic C types enumerated in AtomicToken, above. The type may
// then be further modified by one or more of unsigned, signed, long,

View File

@ -22,6 +22,7 @@
#define LOCAL_LIBS \
downloader express pandabase
#define OTHER_LIBS \
pandaexpress:m \
interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m

View File

@ -32,6 +32,7 @@ public:
Buffer(int size);
~Buffer();
PUBLISHED:
INLINE int get_length(void) const;
#ifndef CPPPARSER

View File

@ -1,5 +1,6 @@
forcetype PandaSystem
forcetype DSearchPath
forcetype DSearchPath::Results
forcetype Filename
forcetype GlobPattern
forcetype Notify

View File

@ -34,6 +34,7 @@
#include <algorithm>
////////////////////////////////////////////////////////////////////
// Class : Patchfile
// Description :

View File

@ -51,7 +51,7 @@
// Note that in the above example, unlike an STL vector (but like a
// C-style array), assigning a PointerToArray object from another
// simply copies the pointer, and does not copy individual elements.
// (Of course, reference counts are adjusted appropriately.) If you
// (Of course, reference counts are adjusted appropriately7.) If you
// actually wanted an element-by-element copy of the array, you would
// do this:
//

View File

@ -284,3 +284,23 @@ none() {
return _none;
}
////////////////////////////////////////////////////////////////////
// Function: get_best_parent_from_Set
// Access: Published
// Description: Return the Index of the BEst fit Classs from a set
////////////////////////////////////////////////////////////////////
INLINE int TypeHandle::get_best_parent_from_Set(const std::set< int > &legal_vals) const
{
if(legal_vals.find(_index) != legal_vals.end())
return _index;
for(int pi = 0; pi < get_num_parent_classes() ; pi++)
{
TypeHandle ph = get_parent_class(pi);
int val = ph.get_best_parent_from_Set(legal_vals);
if(val > 0)
return val;
}
return -1;
}

View File

@ -25,6 +25,8 @@
#include "config_express.h"
#include "set"
// The following illustrates the convention for declaring a type that
// uses TypeHandle. In this example, ThisThingie inherits from
// TypedObject, which automatically supplies some type-differentiation
@ -114,6 +116,8 @@ PUBLISHED:
INLINE TypeHandle get_parent_towards(TypeHandle ancestor,
TypedObject *object = (TypedObject *)NULL) const;
INLINE int get_best_parent_from_Set(const std::set< int > &legal_vals) const;
INLINE int get_index() const;
INLINE void output(ostream &out) const;

View File

@ -615,5 +615,42 @@ look_up(TypeHandle handle, TypedObject *object) const {
return _handle_registry[handle._index];
}
////////////////////////////////////////////////////////////////////
// Function: find_type_by_id
// Access: Private
///////////////////////////////////////////////////////////////////
TypeHandle TypeRegistry::find_type_by_id(int id) const
{
if (id < 0 ||id >= (int)_handle_registry.size())
{
express_cat->fatal()
<< "Invalid TypeHandle index " << id
<< "! Is memory corrupt?\n";
//nassertr(false, NULL);
return TypeHandle::none();
}
return _handle_registry[id]->_handle;
};
////////////////////////////////////////////////////////////////////
// Function: get_best_parent_from_Set
// Access: Private
///////////////////////////////////////////////////////////////////
extern "C" int get_best_parent_from_Set(int id, const std::set<int> &set)
{
// most common case..
if(set.find(id) != set.end())
return id;
TypeHandle th = TypeRegistry::ptr()->find_type_by_id(id);
if(th == TypeHandle::none())
return -1;
return th.get_best_parent_from_Set(set);
}
#endif // NDEBUG

View File

@ -48,10 +48,12 @@ public:
void record_derivation(TypeHandle child, TypeHandle parent);
void record_alternate_name(TypeHandle type, const string &name);
TypeHandle find_type_by_id(int id) const;
PUBLISHED:
TypeHandle find_type(const string &name) const;
string get_name(TypeHandle type, TypedObject *object) const;
INLINE bool is_derived_from(TypeHandle child, TypeHandle base,
TypedObject *child_object);
@ -111,6 +113,10 @@ private:
static TypeRegistry *_global_pointer;
};
///////////////////////////////////////////
// Helper function to allow for "C" interaction into the type system
extern "C" EXPCL_PANDAEXPRESS int get_best_parent_from_Set(int id, const std::set<int> &set);
#include "typeRegistry.I"
#endif

View File

@ -82,3 +82,15 @@ is_exact_type(TypeHandle handle) const {
#endif
return get_type() == handle;
}
////////////////////////////////////////////////////////////////////
// Function: TypedObject::is_exact_type
// Access: Public
// Description: Returns true if the current object is the indicated
// type exactly.
////////////////////////////////////////////////////////////////////
INLINE int TypedObject::
get_best_parent_from_Set(const std::set<int> &inset) const
{
return get_type().get_best_parent_from_Set(inset);
}

View File

@ -24,6 +24,7 @@
#include "typeHandle.h"
#include "register_type.h"
#include "set"
////////////////////////////////////////////////////////////////////
// Class : TypedObject
@ -120,6 +121,7 @@ PUBLISHED:
INLINE int get_type_index() const;
INLINE bool is_of_type(TypeHandle handle) const;
INLINE bool is_exact_type(TypeHandle handle) const;
INLINE int get_best_parent_from_Set(const std::set<int> &) const;
public:
// Derived classes should override this function to call

View File

@ -30,6 +30,7 @@ class VirtualFileMount;
class VirtualFileList;
class VirtualFileSystem;
////////////////////////////////////////////////////////////////////
// Class : VirtualFile
// Description : The abstract base class for a file or directory
@ -93,6 +94,7 @@ private:
INLINE ostream &operator << (ostream &out, const VirtualFile &file);
#include "virtualFile.I"
#endif

View File

@ -48,6 +48,7 @@ private:
Files _files;
};
#include "virtualFileList.I"
#endif

View File

@ -1,4 +1,11 @@
forcetype PointerToBase< RefCountObj< pvector<LPoint2f>>>
forcetype PointerToBase< RefCountObj< pvector<LPoint3f>>>
forcetype PointerToBase< RefCountObj< pvector<LVector3f>>>
forcetype PointerToBase< RefCountObj< pvector<LVecBase4f>>>
renametype LPoint2f LPoint2f
renametype LPoint3f LPoint3f
renametype LPoint4f LPoint4f

View File

@ -1 +1,2 @@
forcetype PointerTo<Connection>
forcetype PointerToBase<Connection>

View File

@ -30,8 +30,9 @@
// forces to them.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAPHYSICS AngularIntegrator : public BaseIntegrator {
public:
PUBLISHED:
virtual ~AngularIntegrator();
public:
void integrate(Physical *physical, AngularForceVector &forces,
float dt);

View File

@ -31,8 +31,9 @@
// forces to them.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAPHYSICS LinearIntegrator : public BaseIntegrator {
public:
PUBLISHED:
virtual ~LinearIntegrator();
public:
void integrate(Physical *physical, LinearForceVector &forces,
float dt);

View File

@ -38,8 +38,10 @@ EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToBase<RefCountObj<vector
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, PointerToArray<int>)
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, ConstPointerToArray<int>)
BEGIN_PUBLISH
typedef PointerToArray<int> PTA_int;
typedef ConstPointerToArray<int> CPTA_int;
END_PUBLISH
// Tell GCC that we'll take care of the instantiation explicitly here.
#ifdef __GNUC__