これは、ctypes を使用して Cygwin API を呼び出すことで可能になります。以下のコードは私にとってはうまくいきます。私は Windows 2012 で 64 ビットの cygwin DLL バージョン 2.5.2 を使用しています。これは Python 2.7.10 と Python 3.4.3 の両方の Cygwin バージョンで動作します。
基本的にcygwin_create_path
fromを呼び出しcygwin1.dll
てパス変換を実行します。malloc
この関数は、変換されたパスを含むメモリ バッファを ( を使用して) 割り当てます。free
そのため、 fromを使用しcygwin1.dll
て、割り当てたバッファを解放する必要があります。
以下は、 6 (Python 2/3 互換ライブラリ)xunicode
の貧弱な代替案であることに注意してください。Python 2 と 3 の両方をサポートする必要がある場合は、6 の方がはるかに良い答えですが、バンドルされていないモジュールに依存しないようにサンプルを作成したかったため、このようにしました。
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)