1
0
mirror of https://github.com/thp/pyotherside.git synced 2025-02-05 08:08:23 +08:00

Load libpython globally on Linux distributions

This commit is contained in:
Thomas Perl 2013-11-02 14:33:56 +01:00
parent 5dbde1fc30
commit 5289b79e7d
4 changed files with 112 additions and 0 deletions

View File

@ -0,0 +1,74 @@
/**
* PyOtherSide: Asynchronous Python 3 Bindings for Qt 5
* Copyright (c) 2013, Thomas Perl <m@thp.io>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
**/
#include "global_libpython_loader.h"
namespace GlobalLibPythonLoader {
#ifdef __linux__
#define _GNU_SOURCE
#include <link.h>
#include <stdio.h>
#include <string.h>
static int load_python_globally_callback(struct dl_phdr_info *info, size_t size, void *data)
{
int major, minor;
char *basename = strrchr(info->dlpi_name, '/');
int *success = (int *)data;
if (basename != NULL) {
if (sscanf(basename, "/libpython%d.%d.so", &major, &minor) != 2) {
if (sscanf(basename, "/libpython%d.%dm.so", &major, &minor) != 2) {
return 0;
}
}
void *pylib = dlopen(info->dlpi_name, RTLD_GLOBAL | RTLD_NOW);
if (pylib != NULL) {
*success = 1;
} else {
fprintf(stderr, "Could not load python library '%s': %s\n",
info->dlpi_name, dlerror());
}
}
return 0;
}
bool loadPythonGlobally()
{
int success = 0;
dl_iterate_phdr(load_python_globally_callback, &success);
return success;
}
#else /* __linux__ */
bool loadPythonGlobally()
{
/* On non-Linux systems, no need to load globally */
return true;
}
#endif /* __linux__ */
}; /* namespace GlobalLibPythonLoader */

View File

@ -0,0 +1,26 @@
/**
* PyOtherSide: Asynchronous Python 3 Bindings for Qt 5
* Copyright (c) 2013, Thomas Perl <m@thp.io>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
**/
#ifndef PYOTHERSIDE_GLOBAL_LIBPYTHON_LOADER_H
#define PYOTHERSIDE_GLOBAL_LIBPYTHON_LOADER_H
namespace GlobalLibPythonLoader {
bool loadPythonGlobally();
};
#endif /* PYOTHERSIDE_GLOBAL_LIBPYTHON_LOADER_H */

View File

@ -19,6 +19,7 @@
#include "qpython_priv.h"
#include "qpython.h"
#include "qpython_imageprovider.h"
#include "global_libpython_loader.h"
#include "pyotherside_plugin.h"
@ -42,6 +43,13 @@ void
PyOtherSideExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
{
Q_ASSERT(QString(PYOTHERSIDE_PLUGIN_ID) == uri);
// In some Linux distributions, the plugin (and subsequently libpython)
// isn't loaded with the RTLD_GLOBAL flag, so symbols in libpython that
// are needed by shared Python modules won't be resolved unless we also
// load libpython again RTLD_GLOBAL again. We do this here.
GlobalLibPythonLoader::loadPythonGlobally();
engine->addImageProvider(PYOTHERSIDE_IMAGEPROVIDER_ID, new QPythonImageProvider);
}

View File

@ -32,6 +32,10 @@ HEADERS += qpython_worker.h
SOURCES += qpython_priv.cpp
HEADERS += qpython_priv.h
# Globally Load Python hack
SOURCES += global_libpython_loader.cpp
HEADERS += global_libpython_loader.h
# Type System Conversion Logic
HEADERS += converter.h
HEADERS += qvariant_converter.h