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_END_PUBLISH
%token KW_ENUM
%token KW_EXTENSION
%token KW_EXTERN
%token KW_EXPLICIT
%token KW_PUBLISHED
@ -547,6 +548,10 @@ storage_class:
| storage_class KW_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,
// e.g. for a function or method.
enum StorageClass {
SC_static = 0x001,
SC_extern = 0x002,
SC_c_binding = 0x004,
SC_virtual = 0x008,
SC_inline = 0x010,
SC_explicit = 0x020,
SC_register = 0x040,
SC_pure_virtual = 0x080,
SC_volatile = 0x100,
SC_mutable = 0x200,
SC_static = 0x0001,
SC_extern = 0x0002,
SC_c_binding = 0x0004,
SC_virtual = 0x0008,
SC_inline = 0x0010,
SC_explicit = 0x0020,
SC_register = 0x0040,
SC_pure_virtual = 0x0080,
SC_volatile = 0x0100,
SC_mutable = 0x0200,
// 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
// BLOCKING macro (i.e. the special __blocking keyword). These
// are methods that might block and therefore need to release
// 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);

View File

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

View File

@ -325,12 +325,29 @@
#define END_PUBLISH __end_publish
#define BLOCKING __blocking
#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
#define BEGIN_PUBLISH
#define END_PUBLISH
#define BLOCKING
#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
#ifdef __cplusplus

View File

@ -44,6 +44,7 @@ FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc,
_ForcedVoidReturn = false;
_has_this = false;
_blocking = false;
_extension = false;
_const_method = false;
_first_true_parameter = 0;
_num_default_parameters = num_default_parameters;
@ -115,10 +116,11 @@ string FunctionRemap::call_function(ostream &out, int indent_level, bool convert
InterfaceMaker::indent(out, indent_level)
<< "unref_delete(" << container << ");\n";
} else {
if(inside_python_native)
if (inside_python_native) {
InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self); \n";
else
InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n";
} else {
InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n";
}
}
} else if (_type == T_typecast_method) {
@ -376,8 +378,7 @@ 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 {
@ -388,23 +389,41 @@ 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);
} else if (_has_this && !container.empty()) {
// If we have a "this" parameter, the calling convention is also
// a bit different.
call << "(" << container << ")->" << _cppfunc->get_local_name();
} else {
call << _cppfunc->get_local_name(&parser);
}
const char *separator = "";
call << "(";
// 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 {
if (_type == T_constructor) {
// Constructors are called differently.
call << _cpptype->get_local_name(&parser);
} else if (_has_this && !container.empty()) {
// If we have a "this" parameter, the calling convention is also
// a bit different.
call << "(" << container << ")->" << _cppfunc->get_local_name();
} else {
call << _cppfunc->get_local_name(&parser);
}
call << "(";
}
if (_flags & F_explicit_self) {
// Pass on the PyObject * that we stripped off above.
call << separator << "self";
@ -472,11 +491,14 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
_type = T_setter;
}
if (_cpptype != (CPPType *)NULL &&
((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0)) {
if ((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0) {
// If it's marked as a "blocking" method or function, record that.
_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();

View File

@ -97,6 +97,7 @@ public:
bool _ForcedVoidReturn;
bool _has_this;
bool _blocking;
bool _extension;
bool _const_method;
int _first_true_parameter;
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";
if (build_python_native )
{
if(library_name.size() > 1)
declaration_bodies << "#define PANDA_LIBRARY_NAME_" << library_name << "\n";
if (build_python_native) {
if (library_name.size() > 1) {
declaration_bodies << "#define PANDA_LIBRARY_NAME_" << library_name << "\n";
}
declaration_bodies << "#include \"py_panda.h\" \n";
}
declaration_bodies << "\n";
@ -396,6 +396,12 @@ void InterrogateBuilder::write_code(ostream &out_code,ostream * out_include, Int
} else {
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";
@ -921,7 +927,7 @@ in_noinclude(const string &name) const {
////////////////////////////////////////////////////////////////////
bool InterrogateBuilder::
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)) {
return false;
}