mirror of
https://github.com/vim/vim.git
synced 2025-08-23 19:34:27 -04:00
patch 9.0.2026: win32: python3 dll loading can be improved
Problem: win32: python3 dll loading can be improved Solution: Load DLL from registry path Support loading python3.dll and/or python3xx.dll from the path written in the registry. To support Stable ABI's forwarder DLL (python3.dll), use the `LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR` flag for `LoadLibraryExW()` because python3xx.dll is placed in the same directory of python3.dll. If Stable ABI is used, search the latest version from the registry (both from HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE). If Stable ABI is not used, search only the matching version. closes: #13315 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Ken Takata <kentkt@csc.jp>
This commit is contained in:
parent
989426be6e
commit
ae3cfa47d3
@ -754,8 +754,10 @@ you can use Vim without this file.
|
|||||||
MS-Windows ~
|
MS-Windows ~
|
||||||
|
|
||||||
To use the Python interface the Python DLL must be in your search path. In a
|
To use the Python interface the Python DLL must be in your search path. In a
|
||||||
console window type "path" to see what directories are used. The 'pythondll'
|
console window type "path" to see what directories are used. If the DLL is
|
||||||
or 'pythonthreedll' option can be also used to specify the Python DLL.
|
not found in your search path, Vim will check the registry to find the path
|
||||||
|
where Python is installed. The 'pythondll' or 'pythonthreedll' option can be
|
||||||
|
also used to specify the Python DLL.
|
||||||
|
|
||||||
The name of the DLL should match the Python version Vim was compiled with.
|
The name of the DLL should match the Python version Vim was compiled with.
|
||||||
Currently the name for Python 2 is "python27.dll", that is for Python 2.7.
|
Currently the name for Python 2 is "python27.dll", that is for Python 2.7.
|
||||||
@ -782,6 +784,8 @@ and failures. With Stable ABI, this restriction is relaxed, and any Python 3
|
|||||||
library with version of at least |v:python3_version| will work. See
|
library with version of at least |v:python3_version| will work. See
|
||||||
|has-python| for how to check if Stable ABI is supported, or see if version
|
|has-python| for how to check if Stable ABI is supported, or see if version
|
||||||
output includes |+python3/dyn-stable|.
|
output includes |+python3/dyn-stable|.
|
||||||
|
On MS-Windows, 'pythonthreedll' will be set to "python3.dll". When searching
|
||||||
|
the DLL from the registry, Vim will search the latest version of Python.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
10. Python 3 *python3*
|
10. Python 3 *python3*
|
||||||
|
129
src/if_python3.c
129
src/if_python3.c
@ -835,17 +835,16 @@ Py_ssize_t py3_PyList_GET_SIZE(PyObject *op)
|
|||||||
* Look up the library "libname" using the InstallPath registry key.
|
* Look up the library "libname" using the InstallPath registry key.
|
||||||
* Return NULL when failed. Return an allocated string when successful.
|
* Return NULL when failed. Return an allocated string when successful.
|
||||||
*/
|
*/
|
||||||
static char *
|
static WCHAR *
|
||||||
py3_get_system_libname(const char *libname)
|
py3_get_system_libname(const char *libname)
|
||||||
{
|
{
|
||||||
|
const WCHAR *pythoncore = L"Software\\Python\\PythonCore";
|
||||||
const char *cp = libname;
|
const char *cp = libname;
|
||||||
char subkey[128];
|
WCHAR subkey[128];
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
char installpath[MAXPATHL];
|
int i;
|
||||||
LONG len = sizeof(installpath);
|
DWORD j, len;
|
||||||
LSTATUS rc;
|
LSTATUS ret;
|
||||||
size_t sysliblen;
|
|
||||||
char *syslibname;
|
|
||||||
|
|
||||||
while (*cp != '\0')
|
while (*cp != '\0')
|
||||||
{
|
{
|
||||||
@ -857,35 +856,95 @@ py3_get_system_libname(const char *libname)
|
|||||||
}
|
}
|
||||||
++cp;
|
++cp;
|
||||||
}
|
}
|
||||||
vim_snprintf(subkey, sizeof(subkey),
|
|
||||||
# ifdef _WIN64
|
WCHAR keyfound[32];
|
||||||
"Software\\Python\\PythonCore\\%d.%d\\InstallPath",
|
HKEY hKeyTop[] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE};
|
||||||
# else
|
HKEY hKeyFound = NULL;
|
||||||
"Software\\Python\\PythonCore\\%d.%d-32\\InstallPath",
|
# ifdef USE_LIMITED_API
|
||||||
|
long maxminor = -1;
|
||||||
# endif
|
# endif
|
||||||
PY_MAJOR_VERSION, PY_MINOR_VERSION);
|
for (i = 0; i < ARRAY_LENGTH(hKeyTop); i++)
|
||||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subkey, 0, KEY_QUERY_VALUE, &hKey)
|
{
|
||||||
!= ERROR_SUCCESS)
|
long major, minor;
|
||||||
|
|
||||||
|
ret = RegOpenKeyExW(hKeyTop[i], pythoncore, 0, KEY_READ, &hKey);
|
||||||
|
if (ret != ERROR_SUCCESS)
|
||||||
|
continue;
|
||||||
|
for (j = 0;; j++)
|
||||||
|
{
|
||||||
|
WCHAR keyname[32];
|
||||||
|
WCHAR *wp;
|
||||||
|
|
||||||
|
len = ARRAY_LENGTH(keyname);
|
||||||
|
ret = RegEnumKeyExW(hKey, j, keyname, &len,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
if (ret == ERROR_NO_MORE_ITEMS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
major = wcstol(keyname, &wp, 10);
|
||||||
|
if (*wp == L'.')
|
||||||
|
minor = wcstol(wp + 1, &wp, 10);
|
||||||
|
# ifdef _WIN64
|
||||||
|
if (*wp != L'\0')
|
||||||
|
continue;
|
||||||
|
# else
|
||||||
|
if (wcscmp(wp, L"-32") != 0)
|
||||||
|
continue;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (major != PY_MAJOR_VERSION)
|
||||||
|
continue;
|
||||||
|
# ifdef USE_LIMITED_API
|
||||||
|
// Search the latest version.
|
||||||
|
if ((minor > maxminor)
|
||||||
|
&& (minor >= ((Py_LIMITED_API >> 16) & 0xff)))
|
||||||
|
{
|
||||||
|
maxminor = minor;
|
||||||
|
wcscpy(keyfound, keyname);
|
||||||
|
hKeyFound = hKeyTop[i];
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
// Check if it matches with the compiled version.
|
||||||
|
if (minor == PY_MINOR_VERSION)
|
||||||
|
{
|
||||||
|
wcscpy(keyfound, keyname);
|
||||||
|
hKeyFound = hKeyTop[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
# ifdef USE_LIMITED_API
|
||||||
|
if (hKeyFound != NULL)
|
||||||
|
break;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
if (hKeyFound == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
rc = RegQueryValueA(hKey, NULL, installpath, &len);
|
|
||||||
RegCloseKey(hKey);
|
swprintf(subkey, ARRAY_LENGTH(subkey), L"%ls\\%ls\\InstallPath",
|
||||||
if (ERROR_SUCCESS != rc)
|
pythoncore, keyfound);
|
||||||
|
ret = RegGetValueW(hKeyFound, subkey, NULL, RRF_RT_REG_SZ,
|
||||||
|
NULL, NULL, &len);
|
||||||
|
if (ret != ERROR_MORE_DATA && ret != ERROR_SUCCESS)
|
||||||
return NULL;
|
return NULL;
|
||||||
cp = installpath + len;
|
size_t len2 = len / sizeof(WCHAR) + 1 + strlen(libname);
|
||||||
// Just in case registry value contains null terminators.
|
WCHAR *path = alloc(len2 * sizeof(WCHAR));
|
||||||
while (cp > installpath && *(cp-1) == '\0')
|
if (path == NULL)
|
||||||
--cp;
|
return NULL;
|
||||||
|
ret = RegGetValueW(hKeyFound, subkey, NULL, RRF_RT_REG_SZ,
|
||||||
|
NULL, path, &len);
|
||||||
|
if (ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
vim_free(path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
// Remove trailing path separators.
|
// Remove trailing path separators.
|
||||||
while (cp > installpath && (*(cp-1) == '\\' || *(cp-1) == '/'))
|
size_t len3 = wcslen(path);
|
||||||
--cp;
|
if ((len3 > 0) && (path[len3 - 1] == L'/' || path[len3 - 1] == L'\\'))
|
||||||
// Ignore if InstallPath is effectively empty.
|
--len3;
|
||||||
if (cp <= installpath)
|
swprintf(path + len3, len2 - len3, L"\\%hs", libname);
|
||||||
return NULL;
|
return path;
|
||||||
sysliblen = (cp - installpath) + 1 + STRLEN(libname) + 1;
|
|
||||||
syslibname = alloc(sysliblen);
|
|
||||||
vim_snprintf(syslibname, sysliblen, "%.*s\\%s",
|
|
||||||
(int)(cp - installpath), installpath, libname);
|
|
||||||
return syslibname;
|
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@ -923,11 +982,13 @@ py3_runtime_link_init(char *libname, int verbose)
|
|||||||
if (!hinstPy3)
|
if (!hinstPy3)
|
||||||
{
|
{
|
||||||
// Attempt to use the path from InstallPath as stored in the registry.
|
// Attempt to use the path from InstallPath as stored in the registry.
|
||||||
char *syslibname = py3_get_system_libname(libname);
|
WCHAR *syslibname = py3_get_system_libname(libname);
|
||||||
|
|
||||||
if (syslibname != NULL)
|
if (syslibname != NULL)
|
||||||
{
|
{
|
||||||
hinstPy3 = load_dll(syslibname);
|
hinstPy3 = LoadLibraryExW(syslibname, NULL,
|
||||||
|
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
|
||||||
|
LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||||
vim_free(syslibname);
|
vim_free(syslibname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2026,
|
||||||
/**/
|
/**/
|
||||||
2025,
|
2025,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user