Add functionality allowing extension functions to interrogate

This commit is contained in:
rdb 2011-01-02 15:14:02 +00:00
parent 9067399079
commit beb90c565f
7 changed files with 96 additions and 40 deletions

View File

@ -250,6 +250,7 @@ pop_struct() {
%token KW_ELSE %token KW_ELSE
%token KW_END_PUBLISH %token KW_END_PUBLISH
%token KW_ENUM %token KW_ENUM
%token KW_EXTENSION
%token KW_EXTERN %token KW_EXTERN
%token KW_EXPLICIT %token KW_EXPLICIT
%token KW_PUBLISHED %token KW_PUBLISHED
@ -547,6 +548,10 @@ storage_class:
| storage_class KW_BLOCKING | storage_class KW_BLOCKING
{ {
$$ = $1 | (int)CPPInstance::SC_blocking; $$ = $1 | (int)CPPInstance::SC_blocking;
}
| storage_class KW_EXTENSION
{
$$ = $1 | (int)CPPInstance::SC_extension;
} }
; ;

View File

@ -37,25 +37,29 @@ public:
// Some of these flags clearly only make sense in certain contexts, // Some of these flags clearly only make sense in certain contexts,
// e.g. for a function or method. // e.g. for a function or method.
enum StorageClass { enum StorageClass {
SC_static = 0x001, SC_static = 0x0001,
SC_extern = 0x002, SC_extern = 0x0002,
SC_c_binding = 0x004, SC_c_binding = 0x0004,
SC_virtual = 0x008, SC_virtual = 0x0008,
SC_inline = 0x010, SC_inline = 0x0010,
SC_explicit = 0x020, SC_explicit = 0x0020,
SC_register = 0x040, SC_register = 0x0040,
SC_pure_virtual = 0x080, SC_pure_virtual = 0x0080,
SC_volatile = 0x100, SC_volatile = 0x0100,
SC_mutable = 0x200, SC_mutable = 0x0200,
// This bit is only set by CPPStructType::check_virtual(). // This bit is only set by CPPStructType::check_virtual().
SC_inherited_virtual = 0x400, SC_inherited_virtual = 0x0400,
// This is a special "storage class" for methods tagged with the // This is a special "storage class" for methods tagged with the
// BLOCKING macro (i.e. the special __blocking keyword). These // BLOCKING macro (i.e. the special __blocking keyword). These
// are methods that might block and therefore need to release // are methods that might block and therefore need to release
// Python threads for their duration. // Python threads for their duration.
SC_blocking = 0x800, SC_blocking = 0x0800,
// And this is for methods tagged with __extension, which declares
// extension methods defined separately from the source code.
SC_extension = 0x1000,
}; };
CPPInstance(CPPType *type, const string &name, int storage_class = 0); CPPInstance(CPPType *type, const string &name, int storage_class = 0);

View File

@ -1966,6 +1966,7 @@ check_keyword(const string &name) {
if (name == "__end_publish") return KW_END_PUBLISH; if (name == "__end_publish") return KW_END_PUBLISH;
if (name == "enum") return KW_ENUM; if (name == "enum") return KW_ENUM;
if (name == "extern") return KW_EXTERN; if (name == "extern") return KW_EXTERN;
if (name == "__extension") return KW_EXTENSION;
if (name == "explicit") return KW_EXPLICIT; if (name == "explicit") return KW_EXPLICIT;
if (name == "__published") return KW_PUBLISHED; if (name == "__published") return KW_PUBLISHED;
if (name == "false") return KW_FALSE; if (name == "false") return KW_FALSE;

View File

@ -325,12 +325,29 @@
#define END_PUBLISH __end_publish #define END_PUBLISH __end_publish
#define BLOCKING __blocking #define BLOCKING __blocking
#define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name) #define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
#undef USE_STL_ALLOCATOR // Don't try to parse these template classes in interrogate. #undef USE_STL_ALLOCATOR /* Don't try to parse these template classes in interrogate. */
#define EXTENSION(x) __extension x;
#define EXTEND __extension
#define EXT_FUNC(func) ::func()
#define EXT_FUNC_ARGS(func, ...) ::func(__VA_ARGS__)
#define EXT_METHOD(cl, m) cl::m()
#define EXT_METHOD_ARGS(cl, m, ...) cl::m(__VA_ARGS__)
#define EXT_CONST_METHOD(cl, m) cl::m() const
#define EXT_CONST_METHOD_ARGS(cl, m, ...) cl::m(__VA_ARGS__) const
#else #else
#define BEGIN_PUBLISH #define BEGIN_PUBLISH
#define END_PUBLISH #define END_PUBLISH
#define BLOCKING #define BLOCKING
#define MAKE_SEQ(seq_name, num_name, element_name) #define MAKE_SEQ(seq_name, num_name, element_name)
#define EXTENSION(x)
#define EXTEND
/* If you change this, don't forget to also change it in interrogate itself. */
#define EXT_FUNC(cl, m) _ext__ ## m ()
#define EXT_FUNC_ARGS(cl, m, ...) _ext__ ## m (__VA_ARGS__)
#define EXT_METHOD(cl, m) _ext_ ## cl ## _ ## m (cl * _ext_this)
#define EXT_METHOD_ARGS(cl, m, ...) _ext_ ## cl ## _ ## m (cl * _ext_this, __VA_ARGS__)
#define EXT_CONST_METHOD(cl, m) _ext_ ## cl ## _ ## m (const cl * _ext_this)
#define EXT_CONST_METHOD_ARGS(cl, m, ...) _ext_ ## cl ## _ ## m (const cl * _ext_this, __VA_ARGS__)
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -44,6 +44,7 @@ FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc,
_ForcedVoidReturn = false; _ForcedVoidReturn = false;
_has_this = false; _has_this = false;
_blocking = false; _blocking = false;
_extension = false;
_const_method = false; _const_method = false;
_first_true_parameter = 0; _first_true_parameter = 0;
_num_default_parameters = num_default_parameters; _num_default_parameters = num_default_parameters;
@ -115,11 +116,12 @@ string FunctionRemap::call_function(ostream &out, int indent_level, bool convert
InterfaceMaker::indent(out, indent_level) InterfaceMaker::indent(out, indent_level)
<< "unref_delete(" << container << ");\n"; << "unref_delete(" << container << ");\n";
} else { } else {
if(inside_python_native) if (inside_python_native) {
InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self); \n"; InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self); \n";
else } else {
InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n"; InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n";
} }
}
} else if (_type == T_typecast_method) { } else if (_type == T_typecast_method) {
// A typecast method can be invoked implicitly. // A typecast method can be invoked implicitly.
@ -376,8 +378,7 @@ get_call_str(const string &container, const vector_string &pexprs) const {
call << _expression; call << _expression;
} }
} else if (_type == T_setter) } else if (_type == T_setter) {
{
if (!container.empty()) { if (!container.empty()) {
call << "(" << container << ")->" << _expression; call << "(" << container << ")->" << _expression;
} else { } else {
@ -387,6 +388,24 @@ get_call_str(const string &container, const vector_string &pexprs) const {
call << " = "; call << " = ";
_parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs)); _parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs));
} else {
const char *separator = "";
// If this function is marked as having an extension function,
// call that instead. The naming convention of the extension
// function has to match the EXT_IMPL definition in dtoolbase.h.
if (_extension) {
if (_cpptype != NULL) {
call << "_ext_" << _cpptype->get_local_name()
<< _cppfunc->get_local_name() << "(";
} else {
call << "_ext__" << _cppfunc->get_local_name() << "(";
}
if (_has_this && !container.empty()) {
call << container;
separator = ", ";
}
} else { } else {
if (_type == T_constructor) { if (_type == T_constructor) {
@ -402,9 +421,9 @@ get_call_str(const string &container, const vector_string &pexprs) const {
call << _cppfunc->get_local_name(&parser); call << _cppfunc->get_local_name(&parser);
} }
const char *separator = "";
call << "("; call << "(";
}
if (_flags & F_explicit_self) { if (_flags & F_explicit_self) {
// Pass on the PyObject * that we stripped off above. // Pass on the PyObject * that we stripped off above.
call << separator << "self"; call << separator << "self";
@ -472,11 +491,14 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
_type = T_setter; _type = T_setter;
} }
if (_cpptype != (CPPType *)NULL && if ((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0) {
((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0)) {
// If it's marked as a "blocking" method or function, record that. // If it's marked as a "blocking" method or function, record that.
_blocking = true; _blocking = true;
} }
if ((_cppfunc->_storage_class & CPPInstance::SC_extension) != 0) {
// Same with functions or methods marked with "extension".
_extension = true;
}
string fname = _cppfunc->get_simple_name(); string fname = _cppfunc->get_simple_name();

View File

@ -97,6 +97,7 @@ public:
bool _ForcedVoidReturn; bool _ForcedVoidReturn;
bool _has_this; bool _has_this;
bool _blocking; bool _blocking;
bool _extension;
bool _const_method; bool _const_method;
int _first_true_parameter; int _first_true_parameter;
int _num_default_parameters; int _num_default_parameters;

View File

@ -376,10 +376,10 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
declaration_bodies << "#include <sstream>\n"; declaration_bodies << "#include <sstream>\n";
if (build_python_native ) if (build_python_native) {
{ if (library_name.size() > 1) {
if(library_name.size() > 1)
declaration_bodies << "#define PANDA_LIBRARY_NAME_" << library_name << "\n"; declaration_bodies << "#define PANDA_LIBRARY_NAME_" << library_name << "\n";
}
declaration_bodies << "#include \"py_panda.h\" \n"; declaration_bodies << "#include \"py_panda.h\" \n";
} }
declaration_bodies << "\n"; declaration_bodies << "\n";
@ -396,6 +396,12 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
} else { } else {
declaration_bodies << "#include <" << filename << ">\n"; declaration_bodies << "#include <" << filename << ">\n";
} }
// Check if it's a special extension file.
} else if (filename.length() > 6 && filename.substr(filename.length() - 6) == "_ext.I") {
declaration_bodies
<< "#define this _ext_this\n"
<< "#include \"" << filename << "\"\n"
<< "#undef this\n";
} }
} }
declaration_bodies << "\n"; declaration_bodies << "\n";
@ -921,7 +927,7 @@ in_noinclude(const string &name) const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool InterrogateBuilder:: bool InterrogateBuilder::
should_include(const string &filename) const { should_include(const string &filename) const {
// Don't directly include any .cxx or .I files. // Don't directly include any .cxx or .I files, except for extensions.
if (CPPFile::is_c_or_i_file(filename)) { if (CPPFile::is_c_or_i_file(filename)) {
return false; return false;
} }