From 0a43008313424e222e335f910aee58bbe1aa8081 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 30 Dec 2018 16:42:50 +0100 Subject: [PATCH] py_panda: avoid duplicate symbol issues with LINK_ALL_STATIC Fixes #478 --- dtool/src/interrogatedb/py_compat.h | 10 +++- dtool/src/interrogatedb/py_panda.cxx | 3 +- dtool/src/interrogatedb/py_panda.h | 68 +++++++++++++-------------- dtool/src/interrogatedb/py_wrappers.h | 12 ++--- 4 files changed, 51 insertions(+), 42 deletions(-) diff --git a/dtool/src/interrogatedb/py_compat.h b/dtool/src/interrogatedb/py_compat.h index 4872faedc7..11771d1948 100644 --- a/dtool/src/interrogatedb/py_compat.h +++ b/dtool/src/interrogatedb/py_compat.h @@ -31,6 +31,14 @@ #include +#ifndef LINK_ALL_STATIC +# define EXPCL_PYPANDA +#elif defined(__GNUC__) +# define EXPCL_PYPANDA __attribute__((weak)) +#else +# define EXPCL_PYPANDA extern inline +#endif + /* Python 2.4 */ // 2.4 macros which aren't available in 2.3 @@ -99,7 +107,7 @@ typedef int Py_ssize_t; // PyInt_FromSize_t automatically picks the right type. # define PyLongOrInt_AS_LONG PyInt_AsLong -size_t PyLongOrInt_AsSize_t(PyObject *); +EXPCL_PYPANDA size_t PyLongOrInt_AsSize_t(PyObject *); #endif // Which character to use in PyArg_ParseTuple et al for a byte string. diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index 5c984cec82..7c2bef1ce7 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -665,7 +665,8 @@ PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) { // We do expose a dictionay for dtool classes .. this should be removed at // some point.. -PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) { +EXPCL_PYPANDA PyObject * +Dtool_AddToDictionary(PyObject *self1, PyObject *args) { PyObject *self; PyObject *subject; PyObject *key; diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index ec2765e77a..353af53608 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -179,19 +179,19 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\ typedef std::map Dtool_TypeMap; -Dtool_TypeMap *Dtool_GetGlobalTypeMap(); +EXPCL_PYPANDA Dtool_TypeMap *Dtool_GetGlobalTypeMap(); /** */ -void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer); +EXPCL_PYPANDA void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer); -void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const std::string &function_name, bool const_ok, bool report_errors); +EXPCL_PYPANDA void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const std::string &function_name, bool const_ok, bool report_errors); -bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer); +EXPCL_PYPANDA bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer); -bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef, - void **answer, const char *method_name); +EXPCL_PYPANDA bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef, + void **answer, const char *method_name); template INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into); template INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &classdef); @@ -201,7 +201,7 @@ INLINE int DtoolInstance_ComparePointers(PyObject *v1, PyObject *v2); INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op); // Functions related to error reporting. -bool _Dtool_CheckErrorOccurred(); +EXPCL_PYPANDA bool _Dtool_CheckErrorOccurred(); #ifdef NDEBUG #define Dtool_CheckErrorOccurred() (UNLIKELY(_PyErr_OCCURRED() != nullptr)) @@ -209,12 +209,12 @@ bool _Dtool_CheckErrorOccurred(); #define Dtool_CheckErrorOccurred() (UNLIKELY(_Dtool_CheckErrorOccurred())) #endif -PyObject *Dtool_Raise_AssertionError(); -PyObject *Dtool_Raise_TypeError(const char *message); -PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name); -PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute); +EXPCL_PYPANDA PyObject *Dtool_Raise_AssertionError(); +EXPCL_PYPANDA PyObject *Dtool_Raise_TypeError(const char *message); +EXPCL_PYPANDA PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name); +EXPCL_PYPANDA PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute); -PyObject *_Dtool_Raise_BadArgumentsError(); +EXPCL_PYPANDA PyObject *_Dtool_Raise_BadArgumentsError(); #ifdef NDEBUG // Define it to a function that just prints a generic message. #define Dtool_Raise_BadArgumentsError(x) _Dtool_Raise_BadArgumentsError() @@ -226,9 +226,9 @@ PyObject *_Dtool_Raise_BadArgumentsError(); // These functions are similar to Dtool_WrapValue, except that they also // contain code for checking assertions and exceptions when compiling with // NDEBUG mode on. -PyObject *_Dtool_Return_None(); -PyObject *Dtool_Return_Bool(bool value); -PyObject *_Dtool_Return(PyObject *value); +EXPCL_PYPANDA PyObject *_Dtool_Return_None(); +EXPCL_PYPANDA PyObject *Dtool_Return_Bool(bool value); +EXPCL_PYPANDA PyObject *_Dtool_Return(PyObject *value); #ifdef NDEBUG #define Dtool_Return_None() (LIKELY(_PyErr_OCCURRED() == nullptr) ? (Py_INCREF(Py_None), Py_None) : nullptr) @@ -241,19 +241,19 @@ PyObject *_Dtool_Return(PyObject *value); /** * Wrapper around Python 3.4's enum library, which does not have a C API. */ -PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, - const char *module = nullptr); +EXPCL_PYPANDA PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, + const char *module = nullptr); INLINE long Dtool_EnumValue_AsLong(PyObject *value); /** */ -PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int RunTimeType); +EXPCL_PYPANDA PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int RunTimeType); // DTool_CreatePyInstance .. wrapper function to finalize the existance of a // general dtool py instance.. -PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const); +EXPCL_PYPANDA PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const); // These template methods allow use when the Dtool_PyTypedObject is not known. // They require a get_class_type() to be defined for the class. @@ -320,26 +320,26 @@ struct LibraryDef { }; #if PY_MAJOR_VERSION >= 3 -PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def); +EXPCL_PYPANDA PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def); #else -PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename); +EXPCL_PYPANDA PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename); #endif // HACK.... Be carefull Dtool_BorrowThisReference This function can be used to // grab the "THIS" pointer from an object and use it Required to support fom // historical inharatence in the for of "is this instance of".. -PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args); +EXPCL_PYPANDA PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args); #define DTOOL_PyObject_HashPointer DtoolInstance_HashPointer #define DTOOL_PyObject_ComparePointers DtoolInstance_ComparePointers -PyObject * +EXPCL_PYPANDA PyObject * copy_from_make_copy(PyObject *self, PyObject *noargs); -PyObject * +EXPCL_PYPANDA PyObject * copy_from_copy_constructor(PyObject *self, PyObject *noargs); -PyObject * +EXPCL_PYPANDA PyObject * map_deepcopy_to_copy(PyObject *self, PyObject *args); /** @@ -348,14 +348,14 @@ map_deepcopy_to_copy(PyObject *self, PyObject *args); */ ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args); ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args, PyObject *kwds); -bool Dtool_ExtractArg(PyObject **result, PyObject *args, - PyObject *kwds, const char *keyword); -bool Dtool_ExtractArg(PyObject **result, PyObject *args, - PyObject *kwds); -bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, - PyObject *kwds, const char *keyword); -bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, - PyObject *kwds); +EXPCL_PYPANDA bool Dtool_ExtractArg(PyObject **result, PyObject *args, + PyObject *kwds, const char *keyword); +EXPCL_PYPANDA bool Dtool_ExtractArg(PyObject **result, PyObject *args, + PyObject *kwds); +EXPCL_PYPANDA bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, + PyObject *kwds, const char *keyword); +EXPCL_PYPANDA bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, + PyObject *kwds); /** * These functions convert a C++ value into the corresponding Python object. @@ -390,7 +390,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value); template ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair &value); -Dtool_PyTypedObject *Dtool_GetSuperBase(); +EXPCL_PYPANDA Dtool_PyTypedObject *Dtool_GetSuperBase(); #include "py_panda.I" diff --git a/dtool/src/interrogatedb/py_wrappers.h b/dtool/src/interrogatedb/py_wrappers.h index 96375d3598..eb5658cb6b 100644 --- a/dtool/src/interrogatedb/py_wrappers.h +++ b/dtool/src/interrogatedb/py_wrappers.h @@ -49,12 +49,12 @@ struct Dtool_GeneratorWrapper { iternextfunc _iternext_func; }; -Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name); -Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name); -Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name); -Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name); -PyObject *Dtool_NewGenerator(PyObject *self, iternextfunc func); -PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset); +EXPCL_PYPANDA Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name); +EXPCL_PYPANDA Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name); +EXPCL_PYPANDA Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name); +EXPCL_PYPANDA Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name); +EXPCL_PYPANDA PyObject *Dtool_NewGenerator(PyObject *self, iternextfunc func); +EXPCL_PYPANDA PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset); #endif // HAVE_PYTHON