Implement #791: dynamically load python27.dll from DLLs/ directory

This commit is contained in:
Andy Kittner 2013-06-29 14:31:11 +02:00
parent b2dda49234
commit 5ba09ddb93
3 changed files with 112 additions and 20 deletions

View File

@ -12,6 +12,17 @@
#include <Python.h> #include <Python.h>
#define PYTHON_DLL_PATH "\\Dlls\\python27.dll"
static void (*py_initialize)(void) = 0;
static void (*py_finalize)(void) = 0;
static void (*py_set_program_name)(char *) = 0;
static void (*py_set_python_home)(char *) = 0;
static int (*py_run_simple_string_flags)(const char *, PyCompilerFlags *) = 0;
static void (*py_sys_set_argv_ex)(int, char **, int) = 0;
static int (*py_main)(int, char **) = 0;
static int *py_ignore_environment_flag = 0;
static const char *run_openslides_code = static const char *run_openslides_code =
"import openslides_gui.gui;" "import openslides_gui.gui;"
"openslides_gui.gui.main()"; "openslides_gui.gui.main()";
@ -71,14 +82,94 @@ _get_module_name()
return NULL; return NULL;
} }
static void
_fatal_error(const char *text)
{
MessageBoxA(NULL, text, "Fatal error", MB_OK | MB_ICONERROR);
exit(1);
}
static void
_fatal_error_fmt(const char *fmt, ...)
{
int size = 512;
char *buf = malloc(size);
va_list args;
int bytes_written;
if (!buf)
abort();
va_start(args, fmt);
for (;;)
{
bytes_written = vsnprintf(buf, size, fmt, args);
if (bytes_written > -1 && bytes_written < size)
break;
else if (bytes_written > size)
size = bytes_written + 1;
else
size *= 2;
buf = realloc(buf, size);
if (!buf)
abort();
}
va_end(args);
_fatal_error(buf);
}
static void *
_load_func(HMODULE module, const char *name)
{
void *address = GetProcAddress(module, name);
if (!address)
_fatal_error_fmt("Failed to look up symbol %s", name);
return address;
}
static void
_load_python(const char *pyhome)
{
size_t pyhome_len = strlen(pyhome);
size_t size = pyhome_len + strlen(PYTHON_DLL_PATH) + 1;
char *buf = malloc(size);
HMODULE py_dll;
if (!buf)
abort();
memcpy(buf, pyhome, pyhome_len);
memcpy(buf + pyhome_len, PYTHON_DLL_PATH, sizeof(PYTHON_DLL_PATH));
buf[size - 1] = '\0';
py_dll = LoadLibrary(buf);
if (!py_dll)
{
DWORD error = GetLastError();
_fatal_error_fmt("Failed to load %s (error %d)", buf, error);
}
py_initialize = (void (*)(void))_load_func(py_dll, "Py_Initialize");
py_finalize = (void (*)(void))_load_func(py_dll, "Py_Finalize");
py_set_program_name = (void (*)(char *))
_load_func(py_dll, "Py_SetProgramName");
py_set_python_home = (void (*)(char *))
_load_func(py_dll, "Py_SetPythonHome");
py_run_simple_string_flags = (int (*)(const char *, PyCompilerFlags *))
_load_func(py_dll, "PyRun_SimpleStringFlags");
py_sys_set_argv_ex = (void (*)(int, char **, int))
_load_func(py_dll, "PySys_SetArgvEx");
py_main = (int (*)(int, char **))_load_func(py_dll, "Py_Main");
py_ignore_environment_flag = (int *)
_load_func(py_dll, "Py_IgnoreEnvironmentFlag");
}
static int static int
_run() _run()
{ {
if (PyRun_SimpleString(run_openslides_code) != 0) if (py_run_simple_string_flags(run_openslides_code, NULL) != 0)
{ _fatal_error("Failed to execute openslides");
fprintf(stderr, "ERROR: failed to execute openslides\n");
return 1;
}
return 0; return 0;
} }
@ -91,33 +182,33 @@ WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmdline, int show)
int run_py_main = __argc > 1; int run_py_main = __argc > 1;
char *py_home, *sep = NULL; char *py_home, *sep = NULL;
Py_SetProgramName(__argv[0]);
py_home = _get_module_name(); py_home = _get_module_name();
if (!py_home)
_fatal_error("Could not determine portable root directory");
if (py_home) sep = strrchr(py_home, '\\');
sep = strrchr(py_home, '\\');
/* should always be the true */ /* should always be the true */
if (sep) if (sep)
{
*sep = '\0'; *sep = '\0';
Py_SetPythonHome(py_home);
Py_IgnoreEnvironmentFlag = 1; _load_python(py_home);
} py_set_program_name(__argv[0]);
py_set_python_home(py_home);
*py_ignore_environment_flag = 1;
if (run_py_main) if (run_py_main)
{ {
/* we where given extra arguments, behave like python.exe */ /* we where given extra arguments, behave like python.exe */
returncode = Py_Main(__argc, __argv); returncode = py_main(__argc, __argv);
} }
else else
{ {
/* no arguments given => start openslides gui */ /* no arguments given => start openslides gui */
Py_Initialize(); py_initialize();
PySys_SetArgvEx(__argc, __argv, 0); py_sys_set_argv_ex(__argc, __argv, 0);
returncode = _run(); returncode = _run();
Py_Finalize(); py_finalize();
} }
free(py_home); free(py_home);

Binary file not shown.

View File

@ -318,7 +318,7 @@ def compile_openslides_launcher():
return False return False
cc.add_include_dir(distutils.sysconfig.get_python_inc()) cc.add_include_dir(distutils.sysconfig.get_python_inc())
cc.add_library_dir(os.path.join(sys.exec_prefix, "Libs")) cc.define_macro("_CRT_SECURE_NO_WARNINGS")
gui_data_dir = os.path.dirname(openslides_gui.__file__) gui_data_dir = os.path.dirname(openslides_gui.__file__)
gui_data_dir = os.path.join(gui_data_dir, "data") gui_data_dir = os.path.join(gui_data_dir, "data")
@ -343,7 +343,8 @@ def compile_openslides_launcher():
]) ])
cc.link_executable( cc.link_executable(
objs, "extras/win32-portable/openslides", objs, "extras/win32-portable/openslides",
extra_preargs=["/subsystem:windows"], extra_preargs=["/subsystem:windows", "/nodefaultlib:python27.lib"],
libraries = ["user32"]
) )
return True return True
@ -361,7 +362,7 @@ def copy_dlls(odir):
pydllname = "python{0}{1}.dll".format(*sys.version_info[:2]) pydllname = "python{0}{1}.dll".format(*sys.version_info[:2])
src = os.path.join(os.environ["WINDIR"], "System32", pydllname) src = os.path.join(os.environ["WINDIR"], "System32", pydllname)
dest = os.path.join(odir, pydllname) dest = os.path.join(dll_dest, pydllname)
shutil.copyfile(src, dest) shutil.copyfile(src, dest)