Interrogate enum class support (maps to Python 3.4 enums), sanify wrapper code

This commit is contained in:
rdb 2016-05-07 00:42:59 +02:00
parent aa5f2685ab
commit fb78fe6e2a
30 changed files with 4774 additions and 5109 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 2.7. */
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,7 +32,7 @@
#ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
# define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
/* Enabling traces. */
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
@ -40,12 +40,11 @@
extern int cppyydebug;
#endif
/* Tokens. */
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
enum yytokentype
{
REAL = 258,
INTEGER = 259,
CHAR_TOK = 260,
@ -292,40 +291,24 @@ extern int cppyydebug;
#define START_CONST_EXPR 377
#define START_TYPE 378
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
/* Location type. */
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
typedef struct YYLTYPE
typedef struct YYLTYPE YYLTYPE;
struct YYLTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
};
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int cppyyparse (void *YYPARSE_PARAM);
#else
int cppyyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int cppyyparse (void);
#else
int cppyyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
#endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED */

View File

@ -2349,21 +2349,23 @@ enum:
;
enum_decl:
enum_keyword name_no_final ':' enum_element_type
enum_keyword ':' enum_element_type
{
current_enum = new CPPEnumType($2, $4, current_scope, @1.file);
}
| enum_keyword name_no_final
{
current_enum = new CPPEnumType($2, current_scope, @1.file);
}
| enum_keyword ':' enum_element_type
{
current_enum = new CPPEnumType(NULL, $3, current_scope, @1.file);
current_enum = new CPPEnumType($1, NULL, $3, current_scope, NULL, @1.file);
}
| enum_keyword
{
current_enum = new CPPEnumType(NULL, current_scope, @1.file);
current_enum = new CPPEnumType($1, NULL, current_scope, NULL, @1.file);
}
| enum_keyword name_no_final ':' enum_element_type
{
CPPScope *new_scope = new CPPScope(current_scope, $2->_names.back(), V_public);
current_enum = new CPPEnumType($1, $2, $4, current_scope, new_scope, @1.file);
}
| enum_keyword name_no_final
{
CPPScope *new_scope = new CPPScope(current_scope, $2->_names.back(), V_public);
current_enum = new CPPEnumType($1, $2, current_scope, new_scope, @1.file);
}
;
@ -2383,14 +2385,12 @@ enum_body_trailing_comma:
| enum_body_trailing_comma name ','
{
assert(current_enum != NULL);
CPPInstance *inst = current_enum->add_element($2->get_simple_name());
current_scope->add_enum_value(inst, current_lexer, @2);
current_enum->add_element($2->get_simple_name(), NULL, current_lexer, @2);
}
| enum_body_trailing_comma name '=' const_expr ','
{
assert(current_enum != NULL);
CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4);
current_scope->add_enum_value(inst, current_lexer, @2);
current_enum->add_element($2->get_simple_name(), $4, current_lexer, @2);
};
enum_body:
@ -2398,14 +2398,12 @@ enum_body:
| enum_body_trailing_comma name
{
assert(current_enum != NULL);
CPPInstance *inst = current_enum->add_element($2->get_simple_name());
current_scope->add_enum_value(inst, current_lexer, @2);
current_enum->add_element($2->get_simple_name(), NULL, current_lexer, @2);
}
| enum_body_trailing_comma name '=' const_expr
{
assert(current_enum != NULL);
CPPInstance *inst = current_enum->add_element($2->get_simple_name(), $4);
current_scope->add_enum_value(inst, current_lexer, @2);
current_enum->add_element($2->get_simple_name(), $4, current_lexer, @2);
}
;
@ -2413,6 +2411,14 @@ enum_keyword:
KW_ENUM
{
$$ = CPPExtensionType::T_enum;
}
| KW_ENUM KW_CLASS
{
$$ = CPPExtensionType::T_enum_class;
}
| KW_ENUM KW_STRUCT
{
$$ = CPPExtensionType::T_enum_struct;
}
;
@ -3495,6 +3501,24 @@ name:
| KW_OVERRIDE
{
$$ = new CPPIdentifier("override", @1);
}
| KW_SIGNED
{
// This is not a keyword in Python, so it is useful to be able to use this
// in MAKE_PROPERTY definitions, etc.
$$ = new CPPIdentifier("signed", @1);
}
| KW_FLOAT
{
$$ = new CPPIdentifier("float", @1);
}
| KW_PUBLIC
{
$$ = new CPPIdentifier("public", @1);
}
| KW_PRIVATE
{
$$ = new CPPIdentifier("private", @1);
}
;

View File

@ -22,42 +22,53 @@
#include "indent.h"
/**
* Creates an untyped, unscoped enum.
* Creates an untyped enum.
*/
CPPEnumType::
CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
const CPPFile &file) :
CPPExtensionType(T_enum, ident, current_scope, file),
_parent_scope(current_scope),
CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
CPPScope *scope, const CPPFile &file) :
CPPExtensionType(type, ident, current_scope, file),
_scope(scope),
_element_type(NULL),
_last_value(NULL)
{
_parent_scope = (type == T_enum) ? current_scope : scope;
if (ident != NULL) {
ident->_native_scope = current_scope;
}
}
/**
* Creates a typed but unscoped enum.
* Creates a typed enum.
*/
CPPEnumType::
CPPEnumType(CPPIdentifier *ident, CPPType *element_type,
CPPScope *current_scope, const CPPFile &file) :
CPPExtensionType(T_enum, ident, current_scope, file),
_parent_scope(current_scope),
CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
CPPScope *current_scope, CPPScope *scope, const CPPFile &file) :
CPPExtensionType(type, ident, current_scope, file),
_scope(scope),
_element_type(element_type),
_last_value(NULL)
{
_parent_scope = (type == T_enum) ? current_scope : scope;
if (ident != NULL) {
ident->_native_scope = current_scope;
}
}
/**
* Returns true if this is a scoped enum.
*/
bool CPPEnumType::
is_scoped() const {
return (_type != T_enum);
}
/**
* Returns the integral type used to store enum values.
*/
CPPType *CPPEnumType::
get_element_type() {
get_underlying_type() {
if (_element_type == NULL) {
// This enum is untyped. Use a suitable default, ie. 'int'. In the
// future, we might want to check whether it fits in an int.
@ -78,11 +89,18 @@ get_element_type() {
*
*/
CPPInstance *CPPEnumType::
add_element(const string &name, CPPExpression *value) {
add_element(const string &name, CPPExpression *value, CPPPreprocessor *preprocessor, const cppyyltype &pos) {
CPPIdentifier *ident = new CPPIdentifier(name);
ident->_native_scope = _parent_scope;
CPPInstance *inst = new CPPInstance(get_element_type(), ident);
CPPInstance *inst;
if (_type == T_enum) {
// Weakly typed enum.
inst = new CPPInstance(get_underlying_type(), ident);
} else {
// C++11-style strongly typed enum.
inst = new CPPInstance(this, ident);
}
inst->_storage_class |= CPPInstance::SC_constexpr;
_elements.push_back(inst);
@ -104,6 +122,41 @@ add_element(const string &name, CPPExpression *value) {
}
inst->_initializer = value;
_last_value = value;
if (preprocessor != (CPPPreprocessor *)NULL) {
// Same-line comment?
CPPCommentBlock *comment =
preprocessor->get_comment_on(pos.first_line, pos.file);
if (comment == (CPPCommentBlock *)NULL) {
// Nope. Check for a comment before this line.
comment =
preprocessor->get_comment_before(pos.first_line, pos.file);
if (comment != NULL) {
// This is a bit of a hack, but it prevents us from picking up a same-
// line comment from the previous line.
if (comment->_line_number != pos.first_line - 1 ||
comment->_col_number <= pos.first_column) {
inst->_leading_comment = comment;
}
}
} else {
inst->_leading_comment = comment;
}
}
// Add the value to the enum scope (as per C++11), assuming it's not anonymous.
if (_scope != NULL) {
_scope->add_enum_value(inst);
}
// Now add it to the containing scope as well if it's not an "enum class".
if (!is_scoped() && _parent_scope != NULL) {
_parent_scope->add_enum_value(inst);
}
return inst;
}

View File

@ -30,15 +30,16 @@ class CPPScope;
*/
class CPPEnumType : public CPPExtensionType {
public:
CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
const CPPFile &file);
CPPEnumType(CPPIdentifier *ident, CPPType *element_type,
CPPScope *current_scope, const CPPFile &file);
CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
CPPScope *scope, const CPPFile &file);
CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
CPPScope *current_scope, CPPScope *scope, const CPPFile &file);
CPPType *get_element_type();
bool is_scoped() const;
CPPType *get_underlying_type();
CPPInstance *add_element(const string &name,
CPPExpression *value = (CPPExpression *)NULL);
CPPInstance *add_element(const string &name, CPPExpression *value,
CPPPreprocessor *preprocessor, const cppyyltype &pos);
virtual bool is_incomplete() const;
@ -54,6 +55,7 @@ public:
virtual CPPEnumType *as_enum_type();
CPPScope *_parent_scope;
CPPScope *_scope;
CPPType *_element_type;
typedef vector<CPPInstance *> Elements;

View File

@ -949,7 +949,7 @@ determine_type() const {
case CPPDeclaration::ST_enum:
// Convert into integral type.
return t1->as_enum_type()->get_element_type();
return t1->as_enum_type()->get_underlying_type();
case CPPDeclaration::ST_simple:
{

View File

@ -229,6 +229,12 @@ operator << (ostream &out, CPPExtensionType::Type type) {
case CPPExtensionType::T_union:
return out << "union";
case CPPExtensionType::T_enum_class:
return out << "enum class";
case CPPExtensionType::T_enum_struct:
return out << "enum struct";
default:
return out << "***invalid extension type***";
}

View File

@ -34,6 +34,8 @@ public:
T_class,
T_struct,
T_union,
T_enum_class,
T_enum_struct,
};
CPPExtensionType(Type type, CPPIdentifier *ident, CPPScope *current_scope,

View File

@ -124,34 +124,9 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
*
*/
void CPPScope::
add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
const cppyyltype &pos) {
add_enum_value(CPPInstance *inst) {
inst->_vis = _current_vis;
if (inst->_leading_comment == (CPPCommentBlock *)NULL) {
// Same-line comment?
CPPCommentBlock *comment =
preprocessor->get_comment_on(pos.first_line, pos.file);
if (comment == (CPPCommentBlock *)NULL) {
// Nope. Check for a comment before this line.
comment =
preprocessor->get_comment_before(pos.first_line, pos.file);
if (comment != NULL) {
// This is a bit of a hack, but it prevents us from picking up a same-
// line comment from the previous line.
if (comment->_line_number != pos.first_line - 1 ||
comment->_col_number <= pos.first_column) {
inst->_leading_comment = comment;
}
}
} else {
inst->_leading_comment = comment;
}
}
string name = inst->get_simple_name();
if (!name.empty()) {
_enum_values[name] = inst;
@ -183,6 +158,8 @@ define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink) {
break;
case CPPExtensionType::T_enum:
case CPPExtensionType::T_enum_struct:
case CPPExtensionType::T_enum_class:
_enums[name] = type;
break;
}
@ -606,6 +583,11 @@ find_scope(const string &name, bool recurse) const {
if (st != NULL) {
return st->_scope;
}
CPPEnumType *et = type->as_enum_type();
if (et != NULL) {
return et->_scope;
}
}
Using::const_iterator ui;
@ -645,11 +627,16 @@ find_scope(const string &name, CPPDeclaration::SubstDecl &subst,
}
CPPStructType *st = type->as_struct_type();
if (st == NULL) {
return NULL;
if (st != NULL) {
return st->_scope;
}
return st->_scope;
CPPEnumType *et = type->as_enum_type();
if (et != NULL) {
return et->_scope;
}
return NULL;
}
/**

View File

@ -61,9 +61,7 @@ public:
virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void add_enum_value(CPPInstance *inst,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void add_enum_value(CPPInstance *inst);
virtual void define_extension_type(CPPExtensionType *type,
CPPPreprocessor *error_sink = NULL);
virtual void define_namespace(CPPNamespace *scope);

View File

@ -43,11 +43,10 @@ add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
*
*/
void CPPTemplateScope::
add_enum_value(CPPInstance *inst, CPPPreprocessor *preprocessor,
const cppyyltype &pos) {
add_enum_value(CPPInstance *inst) {
inst->_template_scope = this;
assert(_parent_scope != NULL);
_parent_scope->add_enum_value(inst, preprocessor, pos);
_parent_scope->add_enum_value(inst);
}
/**

View File

@ -33,9 +33,7 @@ public:
virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void add_enum_value(CPPInstance *inst,
CPPPreprocessor *preprocessor,
const cppyyltype &pos);
virtual void add_enum_value(CPPInstance *inst);
virtual void define_extension_type(CPPExtensionType *type,
CPPPreprocessor *error_sink = NULL);
virtual void define_namespace(CPPNamespace *scope);

View File

@ -764,10 +764,6 @@ write_prototypes(ostream &out_code, ostream *out_h) {
*out_h << "#include \"py_panda.h\"\n\n";
}
out_code << "//********************************************************************\n";
out_code << "//*** prototypes for .. Global\n";
out_code << "//********************************************************************\n";
/*
for (fi = _functions.begin(); fi != _functions.end(); ++fi)
{
@ -792,9 +788,9 @@ write_prototypes(ostream &out_code, ostream *out_h) {
}
}
out_code << "//********************************************************************\n";
out_code << "//*** prototypes for .. External Objects\n";
out_code << "//********************************************************************\n";
out_code << "/**\n";
out_code << " * Extern declarations for imported classes\n";
out_code << " */\n";
for (std::set<CPPType *>::iterator ii = _external_imports.begin(); ii != _external_imports.end(); ii++) {
CPPType *type = (*ii);
@ -897,9 +893,9 @@ write_prototypes_class_external(ostream &out, Object *obj) {
std::string preferred_name = obj->_itype.get_name();
out << "//********************************************************************\n";
out << "//*** prototypes for external.. " << class_name << "\n";
out << "//********************************************************************\n";
out << "/**\n";
out << " * Forward declaration of class " << class_name << "\n";
out << " */\n";
// This typedef is necessary for class templates since we can't pass a comma
// to a macro function.
@ -915,9 +911,9 @@ write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) {
std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
Functions::iterator fi;
out_code << "//********************************************************************\n";
out_code << "//*** prototypes for .. " << ClassName << "\n";
out_code << "//********************************************************************\n";
out_code << "/**\n";
out_code << " * Forward declarations for top-level class " << ClassName << "\n";
out_code << " */\n";
/*
for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) {
@ -943,9 +939,9 @@ write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) {
*/
void InterfaceMakerPythonNative::
write_functions(ostream &out) {
out << "//********************************************************************\n";
out << "//*** Functions for .. Global\n" ;
out << "//********************************************************************\n";
out << "/**\n";
out << " * Python wrappers for global functions\n" ;
out << " */\n";
FunctionsByIndex::iterator fi;
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
Function *func = (*fi).second;
@ -994,9 +990,9 @@ write_class_details(ostream &out, Object *obj) {
std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
std::string cClassName = obj->_itype.get_true_name();
out << "//********************************************************************\n";
out << "//*** Functions for .. " << cClassName << "\n" ;
out << "//********************************************************************\n";
out << "/**\n";
out << " * Python wrappers for functions of class " << cClassName << "\n" ;
out << " */\n";
// First write out all the wrapper functions for the methods.
for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) {
@ -1183,7 +1179,6 @@ write_sub_module(ostream &out, Object *obj) {
// Object * obj = _objects[_embeded_index] ;
string class_name = make_safe_name(obj->_itype.get_scoped_name());
string class_ptr;
out << " // Module init upcall for " << obj->_itype.get_scoped_name() << "\n";
if (!obj->_itype.is_typedef()) {
out << " // " << *(obj->_itype._cpptype) << "\n";
@ -1242,9 +1237,9 @@ write_sub_module(ostream &out, Object *obj) {
*/
void InterfaceMakerPythonNative::
write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
out << "//********************************************************************\n";
out << "//*** Module Object Linker ..\n";
out << "//********************************************************************\n";
out << "/**\n";
out << " * Module Object Linker ..\n";
out << " */\n";
Objects::iterator oi;
@ -1305,14 +1300,41 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
if (object->_itype.is_enum() && !object->_itype.is_nested() &&
isExportThisRun(object->_itype._cpptype)) {
int enum_count = object->_itype.number_of_enum_values();
if (object->_itype.is_scoped_enum()) {
// Convert as Python 3.4 enum.
CPPType *underlying_type = TypeManager::unwrap_const(object->_itype._cpptype->as_enum_type()->get_underlying_type());
string cast_to = underlying_type->get_local_name(&parser);
out << "#if PY_VERSION_HEX >= 0x03040000\n\n";
out << " // enum class " << object->_itype.get_scoped_name() << "\n";
out << " {\n";
out << " PyObject *members = PyTuple_New(" << enum_count << ");\n";
out << " PyObject *member;\n";
for (int xx = 0; xx < enum_count; xx++) {
out << " member = PyTuple_New(2);\n"
" PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\""
<< object->_itype.get_enum_value_name(xx) << "\"));\n"
" PyTuple_SET_ITEM(member, 1, Dtool_WrapValue(("
<< cast_to << ")" << object->_itype.get_scoped_name() << "::"
<< object->_itype.get_enum_value_name(xx) << "));\n"
" PyTuple_SET_ITEM(members, " << xx << ", member);\n";
}
out << " PyModule_AddObject(module, \"" << object->_itype.get_name()
<< "\", Dtool_EnumType_Create(\"" << object->_itype.get_name()
<< "\", members, \"" << _def->module_name << "\"));\n";
out << " }\n";
out << "#endif\n";
} else {
out << " // enum " << object->_itype.get_scoped_name() << "\n";
for (int xx = 0; xx < enum_count; xx++) {
string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false);
string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true);
string enum_value = "::" + object->_itype.get_enum_value_name(xx);
out << " PyModule_AddIntConstant(module, \"" << name1 << "\", " << enum_value << ");\n";
out << " PyModule_AddObject(module, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n";
if (name1 != name2) {
// Also write the mangled name, for historical purposes.
out << " PyModule_AddIntConstant(module, \"" << name2 << "\", " << enum_value << ");\n";
out << " PyModule_AddObject(module, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n";
}
}
}
}
@ -1360,13 +1382,6 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
}
}
}
out << "//********************************************************************\n";
out << "//*** Module Init Upcall .. Externally Defined Class\n";
out << "//********************************************************************\n";
// for (std::set< std::string >::iterator ii = _external_imports.begin(); ii
// != _external_imports.end(); ii++) out << "Dtool_" <<*ii <<
// "._Dtool_ClassInit(NULL);\n";
out << "}\n\n";
@ -1435,9 +1450,9 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
InterfaceMakerPython::write_module(out, out_h, def);
Objects::iterator oi;
out << "//********************************************************************\n";
out << "//*** Py Init Code For .. GlobalScope\n" ;
out << "//********************************************************************\n";
out << "/**\n";
out << " * Module initialization functions for Python module \"" << def->module_name << "\"\n";
out << " */\n";
out << "#if PY_MAJOR_VERSION >= 3\n"
<< "static struct PyModuleDef python_native_module = {\n"
@ -1452,14 +1467,16 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
<< "#ifdef _WIN32\n"
<< "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << def->module_name << "();\n"
<< "#elif __GNUC__ >= 4\n"
<< "extern \"C\" __attribute__((visibility(\"default\"))) PyInit_" << def->module_name << "();\n"
<< "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << def->module_name << "();\n"
<< "#else\n"
<< "extern \"C\" PyObject *PyInit_" << def->module_name << "();\n"
<< "#endif\n"
<< "\n"
<< "PyObject *PyInit_" << def->module_name << "() {\n"
<< " LibraryDef *refs[] = {&" << def->library_name << "_moddef, NULL};\n"
<< " return Dtool_PyModuleInitHelper(refs, &python_native_module);\n"
<< " PyObject *module = Dtool_PyModuleInitHelper(refs, &python_native_module);\n"
<< " Dtool_" << def->library_name << "_BuildInstants(module);\n"
<< " return module;\n"
<< "}\n"
<< "\n"
<< "#else // Python 2 case\n"
@ -1467,14 +1484,15 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
<< "#ifdef _WIN32\n"
<< "extern \"C\" __declspec(dllexport) void init" << def->module_name << "();\n"
<< "#elif __GNUC__ >= 4\n"
<< "extern \"C\" __attribute__((visibility(\"default\"))) init" << def->module_name << "();\n"
<< "extern \"C\" __attribute__((visibility(\"default\"))) void init" << def->module_name << "();\n"
<< "#else\n"
<< "extern \"C\" void init" << def->module_name << "();\n"
<< "#endif\n"
<< "\n"
<< "void init" << def->module_name << "() {\n"
<< " LibraryDef *refs[] = {&" << def->library_name << "_moddef, NULL};\n"
<< " Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n"
<< " PyObject *module = Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n"
<< " Dtool_" << def->library_name << "_BuildInstants(module);\n"
<< "}\n"
<< "\n"
<< "#endif\n"
@ -1520,9 +1538,9 @@ write_module_class(ostream &out, Object *obj) {
}
Functions::iterator fi;
out << "//********************************************************************\n";
out << "//*** Py Init Code For .. " << ClassName << " | " << export_class_name << "\n" ;
out << "//********************************************************************\n";
out << "/**\n";
out << " * Python method tables for " << ClassName << " (" << export_class_name << ")\n" ;
out << " */\n";
out << "static PyMethodDef Dtool_Methods_" << ClassName << "[] = {\n";
SlottedFunctions slots;
@ -2449,11 +2467,7 @@ write_module_class(ostream &out, Object *obj) {
<< classNameFromCppName(ClassName, false) << "\");\n";
}
out << " std::string ss = os.str();\n";
out << "#if PY_MAJOR_VERSION >= 3\n";
out << " return PyUnicode_FromStringAndSize(ss.data(), ss.length());\n";
out << "#else\n";
out << " return PyString_FromStringAndSize(ss.data(), ss.length());\n";
out << "#endif\n";
out << " return Dtool_WrapValue(ss);\n";
out << "}\n\n";
has_local_repr = true;
}
@ -2479,11 +2493,7 @@ write_module_class(ostream &out, Object *obj) {
out << " local_this->write(os);\n";
}
out << " std::string ss = os.str();\n";
out << "#if PY_MAJOR_VERSION >= 3\n";
out << " return PyUnicode_FromStringAndSize(ss.data(), ss.length());\n";
out << "#else\n";
out << " return PyString_FromStringAndSize(ss.data(), ss.length());\n";
out << "#endif\n";
out << " return Dtool_WrapValue(ss);\n";
out << "}\n\n";
has_local_str = true;
}
@ -3037,7 +3047,7 @@ write_module_class(ostream &out, Object *obj) {
} else if (nested_obj->_itype.is_typedef()) {
++num_dict_items;
} else if (nested_obj->_itype.is_enum()) {
} else if (nested_obj->_itype.is_enum() && !nested_obj->_itype.is_scoped_enum()) {
CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type();
num_dict_items += 2 * enum_type->_elements.size();
}
@ -3095,8 +3105,33 @@ write_module_class(ostream &out, Object *obj) {
// No need to support mangled names for nested typedefs; we only added
// support recently.
} else if (nested_obj->_itype.is_scoped_enum()) {
// Convert enum class as Python 3.4 enum.
int enum_count = nested_obj->_itype.number_of_enum_values();
CPPType *underlying_type = TypeManager::unwrap_const(nested_obj->_itype._cpptype->as_enum_type()->get_underlying_type());
string cast_to = underlying_type->get_local_name(&parser);
out << "#if PY_VERSION_HEX >= 0x03040000\n\n";
out << " // enum class " << nested_obj->_itype.get_scoped_name() << ";\n";
out << " {\n";
out << " PyObject *members = PyTuple_New(" << enum_count << ");\n";
out << " PyObject *member;\n";
for (int xx = 0; xx < enum_count; xx++) {
out << " member = PyTuple_New(2);\n"
" PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\""
<< nested_obj->_itype.get_enum_value_name(xx) << "\"));\n"
" PyTuple_SET_ITEM(member, 1, Dtool_WrapValue(("
<< cast_to << ")" << nested_obj->_itype.get_scoped_name() << "::"
<< nested_obj->_itype.get_enum_value_name(xx) << "));\n"
" PyTuple_SET_ITEM(members, " << xx << ", member);\n";
}
out << " PyDict_SetItemString(dict, \"" << nested_obj->_itype.get_name()
<< "\", Dtool_EnumType_Create(\"" << nested_obj->_itype.get_name()
<< "\", members, \"" << _def->module_name << "\"));\n";
out << " }\n";
out << "#endif\n";
} else if (nested_obj->_itype.is_enum()) {
out << " // Enum " << nested_obj->_itype.get_scoped_name() << ";\n";
out << " // enum " << nested_obj->_itype.get_scoped_name() << ";\n";
CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type();
CPPEnumType::Elements::const_iterator ei;
for (ei = enum_type->_elements.begin(); ei != enum_type->_elements.end(); ++ei) {
@ -3111,9 +3146,9 @@ write_module_class(ostream &out, Object *obj) {
name2 = name1;
}
string enum_value = obj->_itype.get_scoped_name() + "::" + (*ei)->get_simple_name();
out << " PyDict_SetItemString(dict, \"" << name1 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n";
out << " PyDict_SetItemString(dict, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n";
if (name1 != name2) {
out << " PyDict_SetItemString(dict, \"" << name2 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n";
out << " PyDict_SetItemString(dict, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n";
}
}
}
@ -3340,7 +3375,7 @@ write_function_for_name(ostream &out, Object *obj,
int max_required_args = 0;
bool all_nonconst = true;
out << "/******************************************************************\n" << " * Python type method wrapper for\n";
out << "/**\n * Python function wrapper for:\n";
for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
remap = (*ri);
if (is_remap_legal(remap)) {
@ -3369,7 +3404,7 @@ write_function_for_name(ostream &out, Object *obj,
}
}
out << " *******************************************************************/\n";
out << " */\n";
out << function_name << " {\n";
@ -6033,164 +6068,16 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
CPPType *orig_type = return_type->get_orig_type();
CPPType *type = return_type->get_new_type();
if (return_type->new_type_is_atomic_string()) {
if (TypeManager::is_char_pointer(orig_type)) {
indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
indent(out, indent_level) << " Py_INCREF(Py_None);\n";
indent(out, indent_level) << " return Py_None;\n";
indent(out, indent_level) << "} else {\n";
out << "#if PY_MAJOR_VERSION >= 3\n";
indent(out, indent_level) << " return "
<< "PyUnicode_FromString(" << return_expr << ");\n";
out << "#else\n";
indent(out, indent_level) << " return "
<< "PyString_FromString(" << return_expr << ");\n";
out << "#endif\n";
indent(out, indent_level) << "}\n";
} else if (TypeManager::is_wchar_pointer(orig_type)) {
indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
indent(out, indent_level) << " Py_INCREF(Py_None);\n";
indent(out, indent_level) << " return Py_None;\n";
indent(out, indent_level) << "} else {\n";
indent(out, indent_level+2)
<< "return PyUnicode_FromWideChar("
<< return_expr << ", wcslen(" << return_expr << "));\n";
indent(out, indent_level) << "}\n";
} else if (TypeManager::is_wstring(orig_type)) {
if (return_type->new_type_is_atomic_string() ||
TypeManager::is_simple(type) ||
TypeManager::is_char_pointer(type) ||
TypeManager::is_wchar_pointer(type) ||
TypeManager::is_pointer_to_PyObject(type) ||
TypeManager::is_pointer_to_Py_buffer(type)) {
// Most types are now handled by the many overloads of Dtool_WrapValue,
// defined in py_panda.h.
indent(out, indent_level)
<< "return PyUnicode_FromWideChar("
<< return_expr << ".data(), (int) " << return_expr << ".length());\n";
} else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
indent(out, indent_level) << " Py_INCREF(Py_None);\n";
indent(out, indent_level) << " return Py_None;\n";
indent(out, indent_level) << "} else {\n";
indent(out, indent_level) << " return "
<< "PyUnicode_FromWideChar("
<< return_expr << "->data(), (int) " << return_expr << "->length());\n";
indent(out, indent_level) << "}\n";
} else if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) {
indent(out, indent_level) << "if (" << return_expr<< " == NULL) {\n";
indent(out, indent_level) << " Py_INCREF(Py_None);\n";
indent(out, indent_level) << " return Py_None;\n";
indent(out, indent_level) << "} else {\n";
out << "#if PY_MAJOR_VERSION >= 3\n";
indent(out, indent_level) << " return "
<< "PyUnicode_FromStringAndSize("
<< return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n";
out << "#else\n";
indent(out, indent_level) << " return "
<< "PyString_FromStringAndSize("
<< return_expr << "->data(), (Py_ssize_t)" << return_expr << "->length());\n";
out << "#endif\n";
indent(out, indent_level) << "}\n";
} else {
out << "#if PY_MAJOR_VERSION >= 3\n";
indent(out, indent_level)
<< "return PyUnicode_FromStringAndSize("
<< return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
out << "#else\n";
indent(out, indent_level)
<< "return PyString_FromStringAndSize("
<< return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n";
out << "#endif\n";
}
} else if (TypeManager::is_bool(type)) {
indent(out, indent_level)
<< "return PyBool_FromLong(" << return_expr << ");\n";
} else if (TypeManager::is_ssize(type)) {
indent(out, indent_level)
<< "return PyLongOrInt_FromSsize_t(" << return_expr << ");\n";
} else if (TypeManager::is_size(type)) {
indent(out, indent_level)
<< "return PyLongOrInt_FromSize_t(" << return_expr << ");\n";
} else if (TypeManager::is_char(type)) {
out << "#if PY_MAJOR_VERSION >= 3\n";
indent(out, indent_level)
<< "return PyUnicode_FromStringAndSize(&" << return_expr << ", 1);\n";
out << "#else\n";
indent(out, indent_level)
<< "return PyString_FromStringAndSize(&" << return_expr << ", 1);\n";
out << "#endif\n";
} else if (TypeManager::is_wchar(type)) {
indent(out, indent_level)
<< "return PyUnicode_FromWideChar(&" << return_expr << ", 1);\n";
} else if (TypeManager::is_unsigned_longlong(type)) {
indent(out, indent_level)
<< "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
} else if (TypeManager::is_longlong(type)) {
indent(out, indent_level)
<< "return PyLong_FromLongLong(" << return_expr << ");\n";
} else if (TypeManager::is_unsigned_integer(type)){
indent(out, indent_level)
<< "return PyLongOrInt_FromUnsignedLong(" << return_expr << ");\n";
} else if (TypeManager::is_integer(type)) {
indent(out, indent_level)
<< "return PyLongOrInt_FromLong(" << return_expr << ");\n";
} else if (TypeManager::is_float(type)) {
indent(out, indent_level)
<< "return PyFloat_FromDouble(" << return_expr << ");\n";
} else if (TypeManager::is_char_pointer(type)) {
indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
indent(out, indent_level) << " Py_INCREF(Py_None);\n";
indent(out, indent_level) << " return Py_None;\n";
indent(out, indent_level) << "} else {\n";
out << "#if PY_MAJOR_VERSION >= 3\n";
indent(out, indent_level) << " return "
<< "PyUnicode_FromString(" << return_expr << ");\n";
out << "#else\n";
indent(out, indent_level) << " return "
<< "PyString_FromString(" << return_expr << ");\n";
out << "#endif\n";
indent(out, indent_level) << "}\n";
} else if (TypeManager::is_wchar_pointer(type)) {
indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
indent(out, indent_level) << " Py_INCREF(Py_None);\n";
indent(out, indent_level) << " return Py_None;\n";
indent(out, indent_level) << "} else {\n";
indent(out, indent_level) << " return "
<< "PyUnicode_FromWideChar("
<< return_expr << ", wcslen(" << return_expr << "));\n";
indent(out, indent_level) << "}\n";
} else if (TypeManager::is_pointer_to_PyObject(type)) {
indent(out, indent_level)
<< "return " << return_expr << ";\n";
} else if (TypeManager::is_pointer_to_Py_buffer(type)) {
indent(out, indent_level) << "if (" << return_expr << " == NULL) {\n";
indent(out, indent_level) << " Py_INCREF(Py_None);\n";
indent(out, indent_level) << " return Py_None;\n";
indent(out, indent_level) << "} else {\n";
indent(out, indent_level) << " return "
<< "PyMemoryView_FromBuffer(" << return_expr << ");\n";
indent(out, indent_level) << "}\n";
<< "return Dtool_WrapValue(" << return_expr << ");\n";
} else if (TypeManager::is_pointer(type)) {
bool is_const = TypeManager::is_const_pointer_to_anything(type);
@ -6234,13 +6121,13 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
} else {
indent(out, indent_level) << "Should Never Reach This InterfaceMakerPythonNative::pack_python_value";
// << "return PyLongOrInt_FromLong((int) " << return_expr << ");\n";
// << "return Dtool_Integer((int) " << return_expr << ");\n";
}
} else {
// Return None.
indent(out, indent_level)
<< "return Py_BuildValue(\"\");\n";
<< "return Py_BuildValue(\"\"); // Don't know how to wrap type.\n";
}
}
@ -6288,11 +6175,7 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
" PyObject *tuple = PyTuple_New(count);\n"
"\n"
" for (Py_ssize_t i = 0; i < count; ++i) {\n"
"#if PY_MAJOR_VERSION >= 3\n"
" PyObject *index = PyLong_FromSsize_t(i);\n"
"#else\n"
" PyObject *index = PyInt_FromSsize_t(i);\n"
"#endif\n";
" PyObject *index = Dtool_WrapValue(i);\n";
switch (elem_getter->_args_type) {
case AT_keyword_args:

View File

@ -2838,6 +2838,10 @@ define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) {
return;
}
if (cpptype->is_scoped()) {
itype._flags |= InterrogateType::F_scoped_enum;
}
int next_value = 0;
CPPEnumType::Elements::const_iterator ei;
@ -2919,6 +2923,8 @@ define_extension_type(InterrogateType &itype, CPPExtensionType *cpptype) {
// But we can at least indicate which of the various extension types it is.
switch (cpptype->_type) {
case CPPExtensionType::T_enum:
case CPPExtensionType::T_enum_class:
case CPPExtensionType::T_enum_struct:
itype._flags |= InterrogateType::F_enum;
break;

View File

@ -205,6 +205,14 @@ is_enum() const {
return (_flags & F_enum) != 0;
}
/**
* Returns true if enum values are only available under a scope.
*/
INLINE bool InterrogateType::
is_scoped_enum() const {
return (_flags & F_scoped_enum) != 0;
}
/**
*
*/

View File

@ -65,6 +65,7 @@ public:
INLINE int get_array_size() const;
INLINE bool is_enum() const;
INLINE bool is_scoped_enum() const;
INLINE int number_of_enum_values() const;
INLINE const string &get_enum_value_name(int n) const;
INLINE const string &get_enum_value_scoped_name(int n) const;
@ -136,6 +137,7 @@ private:
F_unpublished = 0x100000,
F_typedef = 0x200000,
F_array = 0x400000,
F_scoped_enum = 0x800000,
};
public:

View File

@ -0,0 +1,203 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file py_panda.I
* @author rdb
* @date 2016-06-06
*/
/**
* Template function that can be used to extract any TypedObject pointer from
* a wrapped Python object.
*/
template<class T> INLINE bool
DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) {
if (DtoolCanThisBeAPandaInstance(self)) {
Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
if (target_class != NULL) {
into = (T*) ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, target_class);
return (into != NULL);
}
}
into = NULL;
return false;
}
/**
* These functions wrap a pointer for a class that defines get_type_handle().
*/
template<class T> INLINE PyObject *
DTool_CreatePyInstance(const T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true);
}
template<class T> INLINE PyObject *
DTool_CreatePyInstance(T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false);
}
template<class T> INLINE PyObject *
DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index());
}
template<class T> INLINE PyObject *
DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index());
}
/**
* The following functions wrap an arbitrary C++ value into a PyObject.
*/
ALWAYS_INLINE PyObject *Dtool_WrapValue(int value) {
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong((long)value);
#else
return PyInt_FromLong((long)value);
#endif
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned int value) {
#if PY_MAJOR_VERSION >= 3 && SIZEOF_INT < SIZEOF_LONG
return PyLong_FromLong((long)value);
#elif PY_MAJOR_VERSION >= 3
return PyLong_FromUnsignedLong((unsigned long)value);
#elif SIZEOF_INT < SIZEOF_LONG
return PyInt_FromLong((long)value);
#else
return (value > LONG_MAX)
? PyLong_FromUnsignedLong((unsigned long)value)
: PyInt_FromLong((long)value);
#endif
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(long value) {
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(value);
#else
return PyInt_FromLong(value);
#endif
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long value) {
#if PY_MAJOR_VERSION >= 3
return PyLong_FromUnsignedLong(value);
#else
return (value > LONG_MAX)
? PyLong_FromUnsignedLong(value)
: PyInt_FromLong((long)value);
#endif
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value) {
return PyLong_FromLongLong(value);
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value) {
return PyLong_FromUnsignedLongLong(value);
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value) {
PyObject *result = (value ? Py_True : Py_False);
Py_INCREF(result);
return result;
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(double value) {
return PyFloat_FromDouble(value);
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value) {
if (value == (const char *)NULL) {
Py_INCREF(Py_None);
return Py_None;
} else {
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromString(value);
#else
return PyString_FromString(value);
#endif
}
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value) {
if (value == (const wchar_t *)NULL) {
Py_INCREF(Py_None);
return Py_None;
} else {
return PyUnicode_FromWideChar(value, (Py_ssize_t)wcslen(value));
}
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string &value) {
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromStringAndSize(value.data(), (Py_ssize_t)value.length());
#else
return PyString_FromStringAndSize(value.data(), (Py_ssize_t)value.length());
#endif
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value) {
return PyUnicode_FromWideChar(value.data(), (Py_ssize_t)value.length());
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value) {
if (value == (const std::string *)NULL) {
Py_INCREF(Py_None);
return Py_None;
} else {
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromStringAndSize(value->data(), (Py_ssize_t)value->length());
#else
return PyString_FromStringAndSize(value->data(), (Py_ssize_t)value->length());
#endif
}
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value) {
if (value == (const std::wstring *)NULL) {
Py_INCREF(Py_None);
return Py_None;
} else {
return PyUnicode_FromWideChar(value->data(), (Py_ssize_t)value->length());
}
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(char value) {
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromStringAndSize(&value, 1);
#else
return PyString_FromStringAndSize(&value, 1);
#endif
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value) {
return PyUnicode_FromWideChar(&value, 1);
}
ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value) {
return value;
}
#if PY_MAJOR_VERSION >= 0x02060000
ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value) {
if (value == (Py_buffer *)NULL) {
return value;
} else {
return PyMemoryView_FromBuffer(value);
}
}
#endif

View File

@ -335,6 +335,33 @@ PyObject *_Dtool_Return(PyObject *value) {
return value;
}
/**
* Creates a Python 3.4-style enum type. Steals reference to 'names'.
*/
PyObject *Dtool_EnumType_Create(const char *name, PyObject *names, const char *module) {
static PyObject *enum_class = NULL;
static PyObject *enum_meta = NULL;
static PyObject *enum_create = NULL;
if (enum_meta == NULL) {
PyObject *enum_module = PyImport_ImportModule("enum");
nassertr_always(enum_module != NULL, NULL);
enum_class = PyObject_GetAttrString(enum_module, "Enum");
enum_meta = PyObject_GetAttrString(enum_module, "EnumMeta");
enum_create = PyObject_GetAttrString(enum_meta, "_create_");
nassertr(enum_meta != NULL, NULL);
}
PyObject *result = PyObject_CallFunction(enum_create, (char *)"OsN", enum_class, name, names);
nassertr(result != NULL, NULL);
if (module != NULL) {
PyObject *modstr = PyUnicode_FromString(module);
PyObject_SetAttrString(result, "__module__", modstr);
Py_DECREF(modstr);
}
return result;
}
/**
*/
@ -833,19 +860,4 @@ PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) {
return PyObject_CallMethod(self, (char *)"__copy__", (char *)"()");
}
/**
* Similar to PyLong_FromUnsignedLong(), but returns either a regular integer
* or a long integer, according to whether the indicated value will fit.
*/
#if PY_MAJOR_VERSION < 3
EXPCL_INTERROGATEDB PyObject *
PyLongOrInt_FromUnsignedLong(unsigned long value) {
if ((long)value < 0) {
return PyLong_FromUnsignedLong(value);
} else {
return PyInt_FromLong((long)value);
}
}
#endif
#endif // HAVE_PYTHON

View File

@ -103,10 +103,6 @@ inline PyObject* doPy_RETURN_FALSE()
#define nb_inplace_divide nb_inplace_true_divide
#define PyLongOrInt_Check(x) PyLong_Check(x)
#define PyLongOrInt_FromSize_t PyLong_FromSize_t
#define PyLongOrInt_FromSsize_t PyLong_FromSsize_t
#define PyLongOrInt_FromLong PyLong_FromLong
#define PyLongOrInt_FromUnsignedLong PyLong_FromUnsignedLong
#define PyLongOrInt_AS_LONG PyLong_AS_LONG
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
@ -114,9 +110,6 @@ inline PyObject* doPy_RETURN_FALSE()
#else
#define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
// PyInt_FromSize_t automatically picks the right type.
#define PyLongOrInt_FromSize_t PyInt_FromSize_t
#define PyLongOrInt_FromSsize_t PyInt_FromSsize_t
#define PyLongOrInt_FromLong PyInt_FromLong
#define PyLongOrInt_AS_LONG PyInt_AsLong
// For more portably defining hash functions.
@ -159,9 +152,6 @@ typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *);
typedef void *(*CoerceFunction)(PyObject *, void *);
typedef void (*ModuleClassInitFunction)(PyObject *module);
// inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int
// type); inline void Dtool_Deallocate_General(PyObject * self); inline
// int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2); THIS IS THE
// INSTANCE CONTAINER FOR ALL panda py objects....
struct Dtool_PyInstDef {
PyObject_HEAD
@ -300,17 +290,7 @@ EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyT
EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
void **answer, const char *method_name);
template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) {
if (DtoolCanThisBeAPandaInstance(self)) {
Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
if (target_class != NULL) {
into = (T*) ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, target_class);
return (into != NULL);
}
}
into = NULL;
return false;
}
template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into);
// Functions related to error reporting.
EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred();
@ -348,6 +328,12 @@ EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value);
#define Dtool_Return(value) _Dtool_Return(value)
#endif
/**
* Wrapper around Python 3.4's enum library, which does not have a C API.
*/
EXPCL_INTERROGATEDB PyObject *Dtool_EnumType_Create(const char *name, PyObject *names,
const char *module = NULL);
/**
*/
@ -359,29 +345,10 @@ EXPCL_INTERROGATEDB PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyT
// These template methods allow use when the Dtool_PyTypedObject is not known.
// They require a get_class_type() to be defined for the class.
template<class T> INLINE PyObject *DTool_CreatePyInstance(const T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true);
}
template<class T> INLINE PyObject *DTool_CreatePyInstance(T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false);
}
template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index());
}
template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) {
Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
nassertr(known_class != NULL, NULL);
return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index());
}
template<class T> INLINE PyObject *DTool_CreatePyInstance(const T *obj, bool memory_rules);
template<class T> INLINE PyObject *DTool_CreatePyInstance(T *obj, bool memory_rules);
template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules);
template<class T> INLINE PyObject *DTool_CreatePyInstanceTyped(T *obj, bool memory_rules);
// Macro(s) class definition .. Used to allocate storage and init some values
// for a Dtool Py Type object.
@ -474,11 +441,32 @@ copy_from_copy_constructor(PyObject *self, PyObject *noargs);
EXPCL_INTERROGATEDB PyObject *
map_deepcopy_to_copy(PyObject *self, PyObject *args);
#if PY_MAJOR_VERSION < 3
// In the Python 3 case, it is defined as a macro, at the beginning of this
// file.
EXPCL_INTERROGATEDB PyObject *
PyLongOrInt_FromUnsignedLong(unsigned long value);
/**
* These functions convert a C++ value into the corresponding Python object.
* This used to be generated by the code generator, but it seems more reliable
* and maintainable to define these as overloads and have the compiler sort
* it out.
*/
ALWAYS_INLINE PyObject *Dtool_WrapValue(int value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned int value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(long value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(long long value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(double value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string &value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(char value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value);
ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value);
#if PY_MAJOR_VERSION >= 0x02060000
ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value);
#endif
EXPCL_INTERROGATEDB extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE;
@ -486,6 +474,8 @@ EXPCL_INTERROGATEDB extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObjec
#define Dtool_Ptr_DTOOL_SUPER_BASE (&Dtool_DTOOL_SUPER_BASE)
#include "py_panda.I"
#endif // HAVE_PYTHON && !CPPPARSER
#endif // PY_PANDA_H_

View File

@ -25,14 +25,7 @@ match_files(const Filename &cwd) const {
PyObject *result = PyList_New(contents.size());
for (size_t i = 0; i < contents.size(); ++i) {
const string &filename = contents[i];
#if PY_MAJOR_VERSION >= 3
// This function expects UTF-8.
PyObject *str = PyUnicode_FromStringAndSize(filename.data(), filename.size());
#else
PyObject *str = PyString_FromStringAndSize(filename.data(), filename.size());
#endif
PyList_SET_ITEM(result, i, str);
PyList_SET_ITEM(result, i, Dtool_WrapValue(contents[i]));
}
return result;

View File

@ -11,16 +11,6 @@
* @date 2011-01-02
*/
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PY_FROM_FLOATTYPE PyLong_FromLong
#else
#define PY_FROM_FLOATTYPE PyInt_FromLong
#endif
#else
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#endif
/**
*
*/
@ -53,7 +43,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
case 2: {
FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2);
@ -89,5 +79,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
// Upcall to LVecBase2.
return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
}
#undef PY_FROM_FLOATTYPE

View File

@ -11,16 +11,6 @@
* @date 2011-01-02
*/
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PY_FROM_FLOATTYPE PyLong_FromLong
#else
#define PY_FROM_FLOATTYPE PyInt_FromLong
#endif
#else
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#endif
/**
*
*/
@ -54,7 +44,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
case 2: {
FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2);
@ -90,5 +80,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
// Upcall to LVecBase2.
return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
}
#undef PY_FROM_FLOATTYPE

View File

@ -11,16 +11,6 @@
* @date 2011-01-02
*/
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PY_FROM_FLOATTYPE PyLong_FromLong
#else
#define PY_FROM_FLOATTYPE PyInt_FromLong
#endif
#else
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#endif
/**
*
*/
@ -56,9 +46,9 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
if (attr_name[0] == 'w') {
return PY_FROM_FLOATTYPE(_this->_v(3));
return Dtool_WrapValue(_this->_v(3));
} else {
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
}
case 2: {
@ -95,5 +85,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
// Upcall to LVecBase4.
return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
}
#undef PY_FROM_FLOATTYPE

View File

@ -14,16 +14,13 @@
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PYNUMBER_FLOATTYPE PyNumber_Long
#define PY_FROM_FLOATTYPE PyLong_FromLong
#define PY_AS_FLOATTYPE PyLong_AS_LONG
#else
#define PYNUMBER_FLOATTYPE PyNumber_Int
#define PY_FROM_FLOATTYPE PyInt_FromLong
#define PY_AS_FLOATTYPE PyInt_AS_LONG
#endif
#else
#define PYNUMBER_FLOATTYPE PyNumber_Float
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble
#endif
@ -88,7 +85,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
case 2: {
FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2);
@ -222,5 +219,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
}
#undef PYNUMBER_FLOATTYPE
#undef PY_FROM_FLOATTYPE
#undef PY_AS_FLOATTYPE

View File

@ -14,16 +14,13 @@
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PYNUMBER_FLOATTYPE PyNumber_Long
#define PY_FROM_FLOATTYPE PyLong_FromLong
#define PY_AS_FLOATTYPE PyLong_AS_LONG
#else
#define PYNUMBER_FLOATTYPE PyNumber_Int
#define PY_FROM_FLOATTYPE PyInt_FromLong
#define PY_AS_FLOATTYPE PyInt_AS_LONG
#endif
#else
#define PYNUMBER_FLOATTYPE PyNumber_Float
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble
#endif
@ -89,7 +86,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
case 2: {
FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2);
@ -225,5 +222,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
}
#undef PYNUMBER_FLOATTYPE
#undef PY_FROM_FLOATTYPE
#undef PY_AS_FLOATTYPE

View File

@ -14,16 +14,13 @@
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PYNUMBER_FLOATTYPE PyNumber_Long
#define PY_FROM_FLOATTYPE PyLong_FromLong
#define PY_AS_FLOATTYPE PyLong_AS_LONG
#else
#define PYNUMBER_FLOATTYPE PyNumber_Int
#define PY_FROM_FLOATTYPE PyInt_FromLong
#define PY_AS_FLOATTYPE PyInt_AS_LONG
#endif
#else
#define PYNUMBER_FLOATTYPE PyNumber_Float
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#define PY_AS_FLOATTYPE (FLOATTYPE)PyFloat_AsDouble
#endif
@ -91,9 +88,9 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
if (attr_name[0] == 'w') {
return PY_FROM_FLOATTYPE(_this->_v(3));
return Dtool_WrapValue(_this->_v(3));
} else {
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
}
case 2: {
@ -233,5 +230,4 @@ __ipow__(PyObject *self, FLOATTYPE exponent) {
}
#undef PYNUMBER_FLOATTYPE
#undef PY_FROM_FLOATTYPE
#undef PY_AS_FLOATTYPE

View File

@ -11,16 +11,6 @@
* @date 2011-01-02
*/
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PY_FROM_FLOATTYPE PyLong_FromLong
#else
#define PY_FROM_FLOATTYPE PyInt_FromLong
#endif
#else
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#endif
/**
*
*/
@ -53,7 +43,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
case 2: {
FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2);
@ -89,5 +79,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
// Upcall to LVecBase2.
return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
}
#undef PY_FROM_FLOATTYPE

View File

@ -11,16 +11,6 @@
* @date 2011-01-02
*/
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PY_FROM_FLOATTYPE PyLong_FromLong
#else
#define PY_FROM_FLOATTYPE PyInt_FromLong
#endif
#else
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#endif
/**
*
*/
@ -54,7 +44,7 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
case 2: {
FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2);
@ -90,5 +80,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
// Upcall to LVecBase3.
return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
}
#undef PY_FROM_FLOATTYPE

View File

@ -11,16 +11,6 @@
* @date 2011-01-02
*/
#ifdef FLOATTYPE_IS_INT
#if PY_MAJOR_VERSION >= 3
#define PY_FROM_FLOATTYPE PyLong_FromLong
#else
#define PY_FROM_FLOATTYPE PyInt_FromLong
#endif
#else
#define PY_FROM_FLOATTYPE PyFloat_FromDouble
#endif
/**
*
*/
@ -56,9 +46,9 @@ __getattr__(PyObject *self, const string &attr_name) const {
switch (attr_name.size()) {
case 1:
if (attr_name[0] == 'w') {
return PY_FROM_FLOATTYPE(_this->_v(3));
return Dtool_WrapValue(_this->_v(3));
} else {
return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x'));
return Dtool_WrapValue(_this->_v(attr_name[0] - 'x'));
}
case 2: {
@ -95,5 +85,3 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) {
// Upcall to LVecBase4.
return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
}
#undef PY_FROM_FLOATTYPE

View File

@ -187,15 +187,9 @@ get_tag_keys() const {
vector_string keys;
_this->get_tag_keys(keys);
PyObject *result = PyList_New(keys.size());
PyObject *result = PyTuple_New(keys.size());
for (size_t i = 0; i < keys.size(); ++i) {
const string &tag_name = keys[i];
#if PY_MAJOR_VERSION >= 3
PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
#else
PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
#endif
PyList_SET_ITEM(result, i, str);
PyTuple_SET_ITEM(result, i, Dtool_WrapValue(keys[i]));
}
return result;
@ -209,15 +203,9 @@ get_python_tag_keys() const {
vector_string keys;
get_python_tag_keys(keys);
PyObject *result = PyList_New(keys.size());
PyObject *result = PyTuple_New(keys.size());
for (size_t i = 0; i < keys.size(); ++i) {
const string &tag_name = keys[i];
#if PY_MAJOR_VERSION >= 3
PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size());
#else
PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size());
#endif
PyList_SET_ITEM(result, i, str);
PyTuple_SET_ITEM(result, i, Dtool_WrapValue(keys[i]));
}
return result;