diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx index 5201978138..2b9dfa5ce3 100644 --- a/dtool/src/interrogate/interrogate_module.cxx +++ b/dtool/src/interrogate/interrogate_module.cxx @@ -128,6 +128,28 @@ int write_python_table_native(ostream &out) { out << "extern void Dtool_" << *ii << "_BuildInstants(PyObject *module);\n"; } + out.put('\n'); + + out << "#if PY_MAJOR_VERSION >= 3 || !defined(NDEBUG)\n" + << "#ifdef _WIN32\n" + << "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << library_name << "();\n" + << "#elif __GNUC__ >= 4\n" + << "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << library_name << "();\n" + << "#else\n" + << "extern \"C\" PyObject *PyInit_" << library_name << "();\n" + << "#endif\n" + << "#endif\n"; + + out << "#if PY_MAJOR_VERSION < 3 || !defined(NDEBUG)\n" + << "#ifdef _WIN32\n" + << "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n" + << "#elif __GNUC__ >= 4\n" + << "extern \"C\" __attribute__((visibility(\"default\"))) void init" << library_name << "();\n" + << "#else\n" + << "extern \"C\" void init" << library_name << "();\n" + << "#endif\n" + << "#endif\n"; + out << "\n" << "#if PY_MAJOR_VERSION >= 3\n" << "static struct PyModuleDef py_" << library_name << "_module = {\n" @@ -139,14 +161,6 @@ int write_python_table_native(ostream &out) { << " NULL, NULL, NULL, NULL\n" << "};\n" << "\n" - << "#ifdef _WIN32\n" - << "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << library_name << "();\n" - << "#elif __GNUC__ >= 4\n" - << "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << library_name << "();\n" - << "#else\n" - << "extern \"C\" PyObject *PyInit_" << library_name << "();\n" - << "#endif\n" - << "\n" << "PyObject *PyInit_" << library_name << "() {\n"; if (track_interpreter) { @@ -184,15 +198,16 @@ int write_python_table_native(ostream &out) { << " return module;\n" << "}\n" << "\n" - << "#else // Python 2 case\n" - << "\n" - << "#ifdef _WIN32\n" - << "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n" - << "#elif __GNUC__ >= 4\n" - << "extern \"C\" __attribute__((visibility(\"default\"))) void init" << library_name << "();\n" - << "#else\n" - << "extern \"C\" void init" << library_name << "();\n" + + << "#ifndef NDEBUG\n" + << "void init" << library_name << "() {\n" + << " PyErr_SetString(PyExc_ImportError, \"" << module_name << " was " + << "compiled for Python \" PY_VERSION \", which is incompatible " + << "with Python 2\");\n" + << "}\n" << "#endif\n" + + << "#else // Python 2 case\n" << "\n" << "void init" << library_name << "() {\n"; @@ -228,6 +243,15 @@ int write_python_table_native(ostream &out) { out << " }\n" << "}\n" + << "\n" + << "#ifndef NDEBUG\n" + << "PyObject *PyInit_" << library_name << "() {\n" + << " PyErr_SetString(PyExc_ImportError, \"" << module_name << " was " + << "compiled for Python \" PY_VERSION \", which is incompatible " + << "with Python 3\");\n" + << " return (PyObject *)NULL;\n" + << "}\n" + << "#endif\n" << "#endif\n" << "\n"; diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index 4c7476261d..508219aecf 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -597,17 +597,18 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) { #endif // Check the version so we can print a helpful error if it doesn't match. string version = Py_GetVersion(); - if (interrogatedb_cat.is_debug()) { - interrogatedb_cat.debug() - << "Python " << version << "\n"; - } if (version[0] != '0' + PY_MAJOR_VERSION || version[2] != '0' + PY_MINOR_VERSION) { - interrogatedb_cat.error() - << "This module was compiled for Python " - << PY_MAJOR_VERSION << "." << PY_MINOR_VERSION << ", which is incompatible " - << "with Python " << version << ".\n"; + // Raise a helpful error message. We can safely do this because the + // signature and behavior for PyErr_SetString has remained consistent. + ostringstream errs; + errs << "this module was compiled for Python " + << PY_MAJOR_VERSION << "." << PY_MINOR_VERSION << ", which is " + << "incompatible with Python " << version.substr(0, 3); + string error = errs.str(); + PyErr_SetString(PyExc_ImportError, error.c_str()); + return (PyObject *)NULL; } // Initialize the base class of everything. @@ -649,6 +650,12 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) { // to do that. Perhaps we'll find a better place for this in the future. static bool initialized_main_dir = false; if (!initialized_main_dir) { + if (interrogatedb_cat.is_debug()) { + // Good opportunity to print this out once, at startup. + interrogatedb_cat.debug() + << "Python " << version << "\n"; + } + // Grab the __main__ module. PyObject *main_module = PyImport_ImportModule("__main__"); if (main_module == NULL) {