Jest to możliwe po wywołaniu interfejsu API Cygwin przy użyciu ctypes. Poniższy kod działa dla mnie - używam 64-bitowej biblioteki DLL cygwin w wersji 2.5.2 na Windows 2012, a to działa na wersjach Cygwin zarówno Python 2.7.10, jak i Python 3.4.3.
Zasadniczo nazywamy cygwin_create_path
z cygwin1.dll
, aby wykonać konwersję ścieżki. Ta funkcja przydziela bufor pamięci (używając malloc
) zawierający skonwertowaną ścieżkę. Tak więc musimy użyć free
z cygwin1.dll
, aby zwolnić bufor, który został przydzielony.
Poniżej znajduje się xunicode
, która jest alternatywą dla biednego człowieka dla six (biblioteka kompatybilności z Pythonem 2/3); jeśli potrzebujesz obsługi zarówno Python 2, jak i 3, sześć jest o wiele lepszą odpowiedzią, ale chciałem, aby mój przykład był wolny od zależności od wszelkich modułów niezwiązanych z pakietem i dlatego zrobiłem to w ten sposób.
from ctypes import cdll, c_void_p, c_int32, cast, c_char_p, c_wchar_p
from sys import version_info
xunicode = str if version_info[0] > 2 else eval("unicode")
# If running under Cygwin Python, just use DLL name
# If running under non-Cygwin Windows Python, use full path to cygwin1.dll
# Note Python and cygwin1.dll must match bitness (i.e. 32-bit Python must
# use 32-bit cygwin1.dll, 64-bit Python must use 64-bit cygwin1.dll.)
cygwin = cdll.LoadLibrary("cygwin1.dll")
cygwin_create_path = cygwin.cygwin_create_path
cygwin_create_path.restype = c_void_p
cygwin_create_path.argtypes = [c_int32, c_void_p]
# Initialise the cygwin DLL. This step should only be done if using
# non-Cygwin Python. If you are using Cygwin Python don't do this because
# it has already been done for you.
cygwin_dll_init = cygwin.cygwin_dll_init
cygwin_dll_init.restype = None
cygwin_dll_init.argtypes = []
cygwin_dll_init()
free = cygwin.free
free.restype = None
free.argtypes = [c_void_p]
CCP_POSIX_TO_WIN_A = 0
CCP_POSIX_TO_WIN_W = 1
CCP_WIN_A_TO_POSIX = 2
CCP_WIN_W_TO_POSIX = 3
def win2posix(path):
"""Convert a Windows path to a Cygwin path"""
result = cygwin_create_path(CCP_WIN_W_TO_POSIX,xunicode(path))
if result is None:
raise Exception("cygwin_create_path failed")
value = cast(result,c_char_p).value
free(result)
return value
def posix2win(path):
"""Convert a Cygwin path to a Windows path"""
result = cygwin_create_path(CCP_POSIX_TO_WIN_W,str(path))
if result is None:
raise Exception("cygwin_create_path failed")
value = cast(result,c_wchar_p).value
free(result)
return value
# Example, convert LOCALAPPDATA to cygwin path and back
from os import environ
localAppData = environ["LOCALAPPDATA"]
print("Original Win32 path: %s" % localAppData)
localAppData = win2posix(localAppData)
print("As a POSIX path: %s" % localAppData)
localAppData = posix2win(localAppData)
print("Back to a Windows path: %s" % localAppData)
Dziękujemy za dzielenie się ctypes kod, ale nie może to działać z WinPython-3.5.2 i 2.7. 10: awarii PY2 na ctypes 'self._handle = _dlopen (self._name tryb,) '' i PY3 w' wynik = cygwin_create_path (CCP_WIN_W_TO_POSIX, xUnikodzie (ścieżki)) OSError: wyjątek dostępu naruszenia pisanie 0x0000000000000000''. Jakieś pomysły? – ankostis
@ankostis, myślę, że problem jest prawdopodobnie w linii 'cygwin = cdll.LoadLibrary (" cygwin1.dll ")'. Z Cygwin Python, 'cygwin1.dll' jest już załadowany do przestrzeni adresowej procesu Python, więc' LoadLibrary' nie ma problemu ze znalezieniem go. Jednakże, ponieważ WinPython jest czystą aplikacją Windows (bez Cygwin), więc 'cygwin1.dll' zwykle nie będzie załadowany, więc musisz podać pełną ścieżkę do' cygwin1.dll'. Ponadto, jeśli twój WinPython jest 64-bitowy, musisz załadować 64-bitowy plik 'cygwin1.dll'; i odwrotnie, jeśli twój WinPython jest 32-bitowy, musisz załadować 32-bitowy plik 'cygwin1.dll'. –
Próbowałem na innym komputerze, jak powiedziałeś, a teraz otrzymuję to: 'Oryginalna ścieżka Win32: C: \ Users \ ankostis \ AppData \ Local 0 [główny] python 772 D: \ Apps \ WinPython-64bit- 3.5.2.1 \ python-3.5.2.amd64 \ python.exe: *** błąd krytyczny - Błąd wewnętrzny: TP_NUM_C_BUFS za mały: 50 1090 [główny] python 772 cygwin_exception :: open_stackdumpfile: Dumping śledzenia stosu do python.exe.stackdump @tokoti (cygwin): ~/Work/gitdb. git $ less python.exe.stackdump' – ankostis