mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
lists and strings will be automatically coerced into a PTA_blah
This commit is contained in:
parent
f59e128425
commit
a942ce5fbf
@ -307,7 +307,18 @@ make_wrapper_entry(FunctionIndex function_index) {
|
||||
_parameters.erase(_parameters.begin() + 1);
|
||||
_flags |= F_explicit_self;
|
||||
}
|
||||
|
||||
} else if (_type == T_constructor) {
|
||||
// We also allow "self" to be passed in to a constructor, even
|
||||
// though the constructor doesn't normally accept a this pointer.
|
||||
// But this makes sense to Python programmers.
|
||||
if (_parameters.size() >= 1 && _parameters[0]._name == "self" &&
|
||||
TypeManager::is_pointer_to_PyObject(_parameters[0]._remap->get_orig_type())) {
|
||||
_parameters.erase(_parameters.begin() + 0);
|
||||
_flags |= F_explicit_self;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!_void_return) {
|
||||
iwrapper._flags |= InterrogateFunctionWrapper::F_has_return;
|
||||
@ -391,24 +402,21 @@ get_call_str(const string &container, const vector_string &pexprs) const {
|
||||
call << _cppfunc->get_local_name(&parser);
|
||||
}
|
||||
|
||||
const char *separator = "";
|
||||
|
||||
call << "(";
|
||||
if (_flags & F_explicit_self) {
|
||||
// Pass on the PyObject * that we stripped off above.
|
||||
call << "self";
|
||||
if (_first_true_parameter < (int)_parameters.size()) {
|
||||
call << ", ";
|
||||
}
|
||||
call << separator << "self";
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
int pn = _first_true_parameter;
|
||||
if (pn < (int)_parameters.size()) {
|
||||
for (int pn = _first_true_parameter;
|
||||
pn < (int)_parameters.size();
|
||||
++pn) {
|
||||
call << separator;
|
||||
_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
|
||||
pn++;
|
||||
while (pn < (int)_parameters.size()) {
|
||||
call << ", ";
|
||||
_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
|
||||
pn++;
|
||||
}
|
||||
separator = ", ";
|
||||
}
|
||||
call << ")";
|
||||
}
|
||||
@ -670,3 +678,26 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
std::string make_safe_name(const std::string & name)
|
||||
{
|
||||
return InterrogateBuilder::clean_identifier(name);
|
||||
|
||||
/*
|
||||
static const char safe_chars2[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
|
||||
std::string result = name;
|
||||
|
||||
size_t pos = result.find_first_not_of(safe_chars2);
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
result[pos] = '_';
|
||||
pos = result.find_first_not_of(safe_chars2);
|
||||
}
|
||||
|
||||
return result;
|
||||
*/
|
||||
}
|
||||
|
@ -126,4 +126,7 @@ private:
|
||||
bool setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_maker);
|
||||
};
|
||||
|
||||
std::string make_safe_name(const std::string & name);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -335,28 +335,6 @@ std::string methodNameFromCppName(InterfaceMaker::Function *func, const std::st
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
std::string make_safe_name(const std::string & name)
|
||||
{
|
||||
return InterrogateBuilder::clean_identifier(name);
|
||||
|
||||
/*
|
||||
static const char safe_chars2[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
|
||||
std::string result = name;
|
||||
|
||||
size_t pos = result.find_first_not_of(safe_chars2);
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
result[pos] = '_';
|
||||
pos = result.find_first_not_of(safe_chars2);
|
||||
}
|
||||
|
||||
return result;
|
||||
*/
|
||||
}
|
||||
|
||||
bool isInplaceFunction(InterfaceMaker::Function *func)
|
||||
{
|
||||
std::string wname = methodNameFromCppName(func,"");
|
||||
@ -2368,6 +2346,24 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
if (remap->_type == FunctionRemap::T_constructor) {
|
||||
is_constructor = true;
|
||||
}
|
||||
|
||||
if (is_constructor && (remap->_flags & FunctionRemap::F_explicit_self) != 0) {
|
||||
// If we'll be passing "self" to the constructor, we need to
|
||||
// pre-initialize it here. Unfortunately, we can't pre-load the
|
||||
// "this" pointer, but the constructor itself can do this.
|
||||
|
||||
indent(out, indent_level)
|
||||
<< "// Pre-initialize self for the constructor\n";
|
||||
|
||||
CPPType *orig_type = remap->_return_type->get_orig_type();
|
||||
TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false);
|
||||
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
|
||||
const InterrogateType &itype = idb->get_type(type_index);
|
||||
indent(out, indent_level)
|
||||
<< "DTool_PyInit_Finalize(self, NULL, &"
|
||||
<< CLASS_PREFEX << make_safe_name(itype.get_scoped_name())
|
||||
<< ", false, false);\n";
|
||||
}
|
||||
|
||||
// Make one pass through the parameter list. We will output a
|
||||
// one-line temporary variable definition for each parameter, while
|
||||
@ -2790,6 +2786,11 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
|
||||
}
|
||||
}
|
||||
|
||||
// Close the extra brace opened within do_assert_init().
|
||||
extra_indent_level -= 2;
|
||||
indent(out, extra_indent_level)
|
||||
<< "}\n";
|
||||
|
||||
if (!extra_param_check.empty()) {
|
||||
extra_indent_level-=4;
|
||||
indent(out,extra_indent_level)<< "}\n";
|
||||
@ -3382,7 +3383,20 @@ bool InterfaceMakerPythonNative::isFunctionWithThis( Function *func)
|
||||
// failed while the C++ code was executing, and report
|
||||
// this failure back to Python.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void InterfaceMakerPythonNative::do_assert_init(ostream &out, int indent_level, bool constructor) const {
|
||||
void InterfaceMakerPythonNative::do_assert_init(ostream &out, int &indent_level, bool constructor) const {
|
||||
// If a method raises TypeError, continue.
|
||||
indent(out, indent_level)
|
||||
<< "if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError)) {\n";
|
||||
indent(out, indent_level + 2)
|
||||
<< "// TypeError raised; continue to next overload type.\n";
|
||||
if (constructor) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "delete return_value;\n";
|
||||
}
|
||||
indent(out, indent_level)
|
||||
<< "} else {\n";
|
||||
indent_level += 2;
|
||||
|
||||
if (watch_asserts) {
|
||||
out << "#ifndef NDEBUG\n";
|
||||
indent(out, indent_level)
|
||||
@ -3393,19 +3407,25 @@ void InterfaceMakerPythonNative::do_assert_init(ostream &out, int indent_level,
|
||||
<< "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n";
|
||||
indent(out, indent_level + 2)
|
||||
<< "notify->clear_assert_failed();\n";
|
||||
if(constructor)
|
||||
indent(out, indent_level + 2) << "return -1;\n";
|
||||
else
|
||||
indent(out, indent_level + 2) << "return (PyObject *)NULL;\n";
|
||||
if (constructor) {
|
||||
indent(out, indent_level + 2) << "delete return_value;\n";
|
||||
indent(out, indent_level + 2) << "return -1;\n";
|
||||
} else {
|
||||
indent(out, indent_level + 2) << "return (PyObject *)NULL;\n";
|
||||
}
|
||||
|
||||
indent(out, indent_level)
|
||||
<< "}\n";
|
||||
out << "#endif\n";
|
||||
indent(out, indent_level)
|
||||
<< "if (PyErr_Occurred()) {\n";
|
||||
if(constructor)
|
||||
indent(out, indent_level + 2) << "return -1;\n";
|
||||
else
|
||||
indent(out, indent_level + 2) << "return (PyObject *)NULL;\n";
|
||||
if (constructor) {
|
||||
indent(out, indent_level + 2) << "delete return_value;\n";
|
||||
indent(out, indent_level + 2) << "return -1;\n";
|
||||
} else {
|
||||
indent(out, indent_level + 2) << "return (PyObject *)NULL;\n";
|
||||
}
|
||||
|
||||
indent(out, indent_level)
|
||||
<< "}\n";
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ private:
|
||||
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;
|
||||
void do_assert_init(ostream &out, int &indent_level, bool constructor) const;
|
||||
public:
|
||||
bool isRemapLegal( FunctionRemap &remap);
|
||||
bool isFunctionLegal( Function *func);
|
||||
|
@ -99,6 +99,7 @@ extern "C" {
|
||||
EXPCL_DTOOLCONFIG int PyString_AsStringAndSize(...);
|
||||
EXPCL_DTOOLCONFIG int PyString_FromString(...);
|
||||
EXPCL_DTOOLCONFIG int PyString_FromStringAndSize(...);
|
||||
EXPCL_DTOOLCONFIG int PyString_Size(...);
|
||||
EXPCL_DTOOLCONFIG int PyString_Type(...);
|
||||
EXPCL_DTOOLCONFIG int PySys_GetObject(...);
|
||||
EXPCL_DTOOLCONFIG int PyThreadState_Clear(...);
|
||||
@ -231,6 +232,7 @@ int PyString_AsString(...) { return 0; }
|
||||
int PyString_AsStringAndSize(...) { return 0; }
|
||||
int PyString_FromString(...) { return 0; }
|
||||
int PyString_FromStringAndSize(...) { return 0; }
|
||||
int PyString_Size(...) { return 0; }
|
||||
int PyString_Type(...) { return 0; }
|
||||
int PySys_GetObject(...) { return 0; }
|
||||
int PyThreadState_Clear(...) { return 0; }
|
||||
|
@ -77,6 +77,77 @@ PointerToArray(const PointerToArray<Element> ©) :
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::Constructor
|
||||
// Access: Published
|
||||
// Description: This special constructor accepts a Python list of
|
||||
// elements, or a Python string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
PointerToArray<Element>::
|
||||
PointerToArray(PyObject *self, PyObject *sequence) :
|
||||
PointerToArrayBase<Element>((ReferenceCountedVector<Element> *)NULL),
|
||||
_type_handle(get_type_handle(Element))
|
||||
{
|
||||
// We have to pre-initialize self's "this" pointer when we receive
|
||||
// self in the constructor--the caller can't initialize this for us.
|
||||
((Dtool_PyInstDef *)self)->_ptr_to_object = this;
|
||||
|
||||
if (!PySequence_Check(sequence)) {
|
||||
// If passed with a non-sequence, this isn't the right constructor.
|
||||
PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a sequence");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PyString_CheckExact(sequence)) {
|
||||
// If we were passed a Python string, then instead of storing it
|
||||
// character-at-a-time, just load the whole string as a data
|
||||
// buffer.
|
||||
int size = PyString_Size(sequence);
|
||||
if (size % sizeof(Element) != 0) {
|
||||
ostringstream stream;
|
||||
stream << "Buffer not a multiple of " << sizeof(Element) << " bytes";
|
||||
string str = stream.str();
|
||||
PyErr_SetString(PyExc_ValueError, str.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
int num_elements = size / sizeof(Element);
|
||||
insert(begin(), num_elements, Element());
|
||||
|
||||
// Hope there aren't any constructors or destructors involved
|
||||
// here.
|
||||
if (size != 0) {
|
||||
const char *data = PyString_AsString(sequence);
|
||||
memcpy(p(), data, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Now construct the internal list by copying the elements
|
||||
// one-at-a-time from Python.
|
||||
int size = PySequence_Size(sequence);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
PyObject *item = PySequence_GetItem(sequence, i);
|
||||
if (item == NULL) {
|
||||
return;
|
||||
}
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)"pushBack", (char *)"O", item);
|
||||
Py_DECREF(item);
|
||||
if (result == NULL) {
|
||||
// Unable to add item--probably it wasn't of the appropriate type.
|
||||
ostringstream stream;
|
||||
stream << "Element " << i << " in sequence passed to PointerToArray constructor could not be added";
|
||||
string str = stream.str();
|
||||
PyErr_SetString(PyExc_TypeError, str.c_str());
|
||||
return;
|
||||
}
|
||||
Py_DECREF(result);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::begin
|
||||
// Access: Public
|
||||
|
@ -67,6 +67,9 @@
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "pointerToArrayBase.h"
|
||||
#ifdef HAVE_PYTHON
|
||||
#include "py_panda.h"
|
||||
#endif
|
||||
|
||||
#if defined(WIN32_VC) && !defined(__INTEL_COMPILER)
|
||||
// disable mysterious MSVC warning for static inline PTA::empty_array method
|
||||
@ -108,6 +111,11 @@ PUBLISHED:
|
||||
INLINE PointerToArray(TypeHandle type_handle = get_type_handle(Element));
|
||||
INLINE static PointerToArray<Element> empty_array(size_type n, TypeHandle type_handle = get_type_handle(Element));
|
||||
INLINE PointerToArray(const PointerToArray<Element> ©);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
PointerToArray(PyObject *self, PyObject *sequence);
|
||||
#endif
|
||||
|
||||
INLINE size_type size() const;
|
||||
INLINE void push_back(const Element &x);
|
||||
INLINE void pop_back();
|
||||
@ -141,6 +149,10 @@ public:
|
||||
INLINE PointerToArray(size_type n, const Element &value, TypeHandle type_handle = get_type_handle(Element));
|
||||
INLINE PointerToArray(const PointerToArray<Element> ©);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
PointerToArray(PyObject *self, PyObject *sequence);
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Duplicating the interface of vector. The following member
|
||||
// functions are all const, because they do not reassign the
|
||||
@ -254,6 +266,7 @@ public:
|
||||
PUBLISHED:
|
||||
INLINE ConstPointerToArray(const PointerToArray<Element> ©);
|
||||
INLINE ConstPointerToArray(const ConstPointerToArray<Element> ©);
|
||||
|
||||
typedef TYPENAME pvector<Element>::size_type size_type;
|
||||
INLINE size_type size() const;
|
||||
INLINE const Element &get_element(size_type n) const;
|
||||
|
@ -13,15 +13,11 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "textureCollection.h"
|
||||
|
||||
#include "indent.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include "py_panda.h"
|
||||
#ifndef CPPPARSER
|
||||
extern EXPCL_PANDA_PUTIL Dtool_PyTypedObject Dtool_Texture;
|
||||
#endif // CPPPARSER
|
||||
#endif // HAVE_PYTHON
|
||||
#include "py_panda.h"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureCollection::Constructor
|
||||
@ -63,7 +59,11 @@ operator = (const TextureCollection ©) {
|
||||
// in the class record.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TextureCollection::
|
||||
TextureCollection(PyObject *sequence) {
|
||||
TextureCollection(PyObject *self, PyObject *sequence) {
|
||||
// We have to pre-initialize self's "this" pointer when we receive
|
||||
// self in the constructor--the caller can't initialize this for us.
|
||||
((Dtool_PyInstDef *)self)->_ptr_to_object = this;
|
||||
|
||||
if (!PySequence_Check(sequence)) {
|
||||
// If passed with a non-sequence, this isn't the right constructor.
|
||||
PyErr_SetString(PyExc_TypeError, "TextureCollection constructor requires a sequence");
|
||||
@ -76,20 +76,17 @@ TextureCollection(PyObject *sequence) {
|
||||
if (item == NULL) {
|
||||
return;
|
||||
}
|
||||
Texture *tex = NULL;
|
||||
DTOOL_Call_ExtractThisPointerForType(item, &Dtool_Texture, (void **)&tex);
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)"addTexture", (char *)"O", item);
|
||||
Py_DECREF(item);
|
||||
if (tex == NULL) {
|
||||
// If one of the items in the sequence is not a Texture, can't
|
||||
// use this constructor.
|
||||
if (result == NULL) {
|
||||
// Unable to add item--probably it wasn't of the appropriate type.
|
||||
ostringstream stream;
|
||||
stream << "Element " << i << " in sequence passed to TextureCollection constructor is not a Texture";
|
||||
stream << "Element " << i << " in sequence passed to TextureCollection constructor could not be added";
|
||||
string str = stream.str();
|
||||
PyErr_SetString(PyExc_TypeError, str.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
add_texture(tex);
|
||||
Py_DECREF(result);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
|
@ -32,7 +32,7 @@ PUBLISHED:
|
||||
INLINE ~TextureCollection();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
TextureCollection(PyObject *sequence);
|
||||
TextureCollection(PyObject *self, PyObject *sequence);
|
||||
PyObject *__reduce__(PyObject *self) const;
|
||||
#endif
|
||||
|
||||
|
@ -18,15 +18,11 @@
|
||||
#include "textureAttrib.h"
|
||||
#include "colorScaleAttrib.h"
|
||||
#include "colorAttrib.h"
|
||||
|
||||
#include "indent.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include "py_panda.h"
|
||||
#ifndef CPPPARSER
|
||||
extern EXPCL_PANDA_PUTIL Dtool_PyTypedObject Dtool_NodePath;
|
||||
#endif // CPPPARSER
|
||||
#endif // HAVE_PYTHON
|
||||
#include "py_panda.h"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePathCollection::Constructor
|
||||
@ -68,7 +64,11 @@ operator = (const NodePathCollection ©) {
|
||||
// in the class record.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NodePathCollection::
|
||||
NodePathCollection(PyObject *sequence) {
|
||||
NodePathCollection(PyObject *self, PyObject *sequence) {
|
||||
// We have to pre-initialize self's "this" pointer when we receive
|
||||
// self in the constructor--the caller can't initialize this for us.
|
||||
((Dtool_PyInstDef *)self)->_ptr_to_object = this;
|
||||
|
||||
if (!PySequence_Check(sequence)) {
|
||||
// If passed with a non-sequence, this isn't the right constructor.
|
||||
PyErr_SetString(PyExc_TypeError, "NodePathCollection constructor requires a sequence");
|
||||
@ -81,20 +81,17 @@ NodePathCollection(PyObject *sequence) {
|
||||
if (item == NULL) {
|
||||
return;
|
||||
}
|
||||
NodePath *np = NULL;
|
||||
DTOOL_Call_ExtractThisPointerForType(item, &Dtool_NodePath, (void **)&np);
|
||||
PyObject *result = PyObject_CallMethod(self, (char *)"addPath", (char *)"O", item);
|
||||
Py_DECREF(item);
|
||||
if (np == NULL) {
|
||||
// If one of the items in the sequence is not a NodePath, can't
|
||||
// use this constructor.
|
||||
if (result == NULL) {
|
||||
// Unable to add item--probably it wasn't of the appropriate type.
|
||||
ostringstream stream;
|
||||
stream << "Element " << i << " in sequence passed to NodePathCollection constructor is not a NodePath";
|
||||
stream << "Element " << i << " in sequence passed to NodePathCollection constructor could not be added";
|
||||
string str = stream.str();
|
||||
PyErr_SetString(PyExc_TypeError, str.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
add_path(*np);
|
||||
Py_DECREF(result);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
|
@ -34,7 +34,7 @@ PUBLISHED:
|
||||
INLINE ~NodePathCollection();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
NodePathCollection(PyObject *sequence);
|
||||
NodePathCollection(PyObject *self, PyObject *sequence);
|
||||
PyObject *__reduce__(PyObject *self) const;
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user