[Python-Dev] The os module, unix and win32
Thomas Heller
theller at python.net
Fri Jan 9 12:04:35 EST 2004
Guido van Rossum <guido at python.org> writes:
>> [Dave]
>>
>> >> Another possibility: we'd get a lot more mileage out of simply
>> >> adding ctypes to the standard install. That would solve the
>> >> immediate popen problem, let us get rid of _winreg entirely (and
>> >> replace it with a pure Python version), and make future Win32
>> >> problems easier to solve.
>>
>> [Guido]
>> > I don't know that a Python version of _winreg using ctypes would be
>> > preferable over a C version.
>>
>> Since there is a C version, there's no need to code it in Python again.
>>
>> > I'd expect it to be slower, less readable than the C version, and more
>> > susceptible to the possibility of causing segfaults.
>>
>> Slower: yes, but I don't know how much.
>> Less readable: no, more readable.
>> Susceptible to segfaults: If written correctly, it should be bullet
>> proof - exactly the same as a C version.
>
> But the version that was referenced here before isn't bulletproof,
> right? Wouldn't the bullet-proofing reduce the readability?
Here is a small part a Dave's code:
def CreateKey(baseKey, subKey):
'Creates/opens the given key and returns it'
RCK = windll.advapi32.RegCreateKeyExA
key = c_int(0)
RCK(baseKey, subKey, 0, 0, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, 0, byref(key), 0)
return key.value
He doesn't check that baseKey and subKey are strings, and he doesn't
check the return value of the function call.
There are several ways to fix these problems. A simple one would be to
write this instead:
def CreateKey(baseKey, subKey):
'Creates/opens the given key and returns it'
RCK = windll.advapi32.RegCreateKeyExA
key = c_int(0)
result = RCK(str(baseKey), str(subKey), 0, 0,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, 0, byref(key), 0):
raise WindowsError(result)
return key.value
But ctypes supports a kind of 'function prototypes' (which do automatic
argument type checking and/or conversion= as well as automatic result
checking:
def CheckNonNull(errcode):
# if errcode is nonzero, raise a WindowsError
if errcode:
raise WindowsError(errcode)
RCK = windll.advapi32.RegCreateKeyExA
# specify the argument types
RCK.argtypes = (HKEY, LPCTSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES,
PMKEY, LPDWROD)
# RegCreateKeyExA returns 0 on success, or a windows error code
RCK.restype = CheckNonNull
def CreateKey(baseKey, subKey):
'Creates/opens the given key and returns it'
key = c_int(0)
RCK(baseKey, subKey, 0, 0,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, 0, byref(key), 0)
return key.value
>
>> > That doesn't mean I don't think ctypes is a good idea -- just that I
>> > don't think applying it to _winreg would be useful.
>>
>> Cool.
>>
>> Should this be a Windows only version, or cross-platform?
>
> I don't know enough about ctypes and its user community to answer that
> (I doubt I'd have much direct need for it myself). But in general I'm
> biased towards cross-platform tools.
I had reports that it works on Solaris, Linux, MacOS, BSD. Maybe more
systems.
The problem is that the non-windows version uses libffi, which is
difficult to find and install - it seems to be maintained now as part of
gcc, although the license is more BSD like.
I would like to get rid of libffi - but the only multi-architecture
alternative I know of is Bruno Haible's ffcall (which is GPL).
There *may* be other options (including writing assembly code).
Sam Rushing's calldll did this, AFAIK.
And, remember: you can write bulletproof code with ctypes, but you can
also easily crash Python. Or other weird things.
Thomas
More information about the Python-Dev
mailing list