You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
wide character parameter handling in ctypes #49369
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee='https://github.com/theller'closed_at=<Date2009-02-03.12:41:54.468>created_at=<Date2009-01-31.20:53:36.488>labels= ['ctypes', 'type-bug']
title='wide character parameter handling in ctypes'updated_at=<Date2009-02-03.12:41:54.467>user='https://github.com/jaraco'
Using Python 2.5.4 and Python 2.6.1 on 32-bit python, when passing a
regular string to a function expecting pointer to a wide string
(wintypes.LPCWSTR), the function executes without problems.
When calling the same using Python 2.6.1 on 64-bit windows, the called
function appears not to recognize the parameter unless it is first
converted to unicode.
I discovered this when calling the WNetAddConnection2 function.
Assuming a properly-initialized NETRESOURCE, resource.
This method works fine on 32-bit python but fails on 64-bit python
unless username=unicode(username). The error returned is "The specified
password is incorrect", indicating that the username is in fact
incorrect because the correct username does not require a password.
I wish I had a better test case; I'll try to track down one that doesn't
require such a complex underlying API.
I'm not sure what the correct fix is for this, but regardless, I would
expect the behavior to be consistent for the same Python version
independent of word size.
After putting together a more simple example without externalities, I'm
unable to continue to assert the discrepancy between 32 and 64-bit
Windows, although I do still see where narrow character strings are
treated as wide character buffers.
See the attached script that demonstrates the issue (on Python 2.5 and
Python 2.6 regardless of word size).
Now the inconsistency seems to only lie with the WNetAddConnection2W
function and not the MessageBoxW function, both of which take LPCTSTR
parameters (at least according to the documentation).
Perhaps this is a non-issue, but I'd be interested to know why the
WNetAddConnection2W example works in 32-bit but not 64-bit. Could it be
the 32-bit WNetAddConnection2W actually attempts to handle the buffer as
both wide and narrow, but MessageBoxW takes it at face value?
I've confirmed that my original assumption was quite false, and that
even if the parameters are the correct width, WNetAddConnection2W
behaves differently in 64-bit windows versus 32-bit windows, so it made
a bad test case.
So I've changed the title of this issue, because I still would like to
know if it is proper for ctypes to accept a narrow string but treat it
as a wide string without converting it.
changed the title [-]inconsistent wide character parameter handling in 64-bit python[/-][+]wide character parameter handling in ctypes[/+]on Jan 31, 2009
I see this in the documentation, which basically answers the question:
"windll does not try to select [wide or narrow functions] by magic, you
must access the version you need by specifying GetModuleHandleA or
GetModuleHandleW explicitely, and then call it with normal strings or
unicode strings respectively."
This behavior is inconsistent with how structures are handled, where
members are up-converted to unicode. For example.
ctypes cannot guess the function signature, and does not know if the function
expects strings or unicodes.
In your examples,
ctypes.windll.user32.MessageBoxW(handle, text, caption, type)
will accept everything you pass, and create C values depending on the types of the
actual values of the parameters: when you pass a unicode, ctypes uses a wchar_t*
buffer; when you pass a narrow string, ctypes uses a char* buffer (and is wrong in
this case).
In your Structure example, you do declare a kind of signature for the Structure.
ctypes is now able to convert the value you give into the declared type.
You can do the same thing with functions, if you provide the signature:
Activity
jaraco commentedon Jan 31, 2009
Using Python 2.5.4 and Python 2.6.1 on 32-bit python, when passing a
regular string to a function expecting pointer to a wide string
(wintypes.LPCWSTR), the function executes without problems.
When calling the same using Python 2.6.1 on 64-bit windows, the called
function appears not to recognize the parameter unless it is first
converted to unicode.
I discovered this when calling the WNetAddConnection2 function.
Assuming a properly-initialized NETRESOURCE, resource.
This method works fine on 32-bit python but fails on 64-bit python
unless username=unicode(username). The error returned is "The specified
password is incorrect", indicating that the username is in fact
incorrect because the correct username does not require a password.
I wish I had a better test case; I'll try to track down one that doesn't
require such a complex underlying API.
I'm not sure what the correct fix is for this, but regardless, I would
expect the behavior to be consistent for the same Python version
independent of word size.
jaraco commentedon Jan 31, 2009
After putting together a more simple example without externalities, I'm
unable to continue to assert the discrepancy between 32 and 64-bit
Windows, although I do still see where narrow character strings are
treated as wide character buffers.
See the attached script that demonstrates the issue (on Python 2.5 and
Python 2.6 regardless of word size).
Now the inconsistency seems to only lie with the WNetAddConnection2W
function and not the MessageBoxW function, both of which take LPCTSTR
parameters (at least according to the documentation).
Perhaps this is a non-issue, but I'd be interested to know why the
WNetAddConnection2W example works in 32-bit but not 64-bit. Could it be
the 32-bit WNetAddConnection2W actually attempts to handle the buffer as
both wide and narrow, but MessageBoxW takes it at face value?
jaraco commentedon Jan 31, 2009
Or alternately, is it possible (and reasonable) for ctypes to inspect
the function signature and create wide character buffers when appropriate?
jaraco commentedon Jan 31, 2009
I've confirmed that my original assumption was quite false, and that
even if the parameters are the correct width, WNetAddConnection2W
behaves differently in 64-bit windows versus 32-bit windows, so it made
a bad test case.
So I've changed the title of this issue, because I still would like to
know if it is proper for ctypes to accept a narrow string but treat it
as a wide string without converting it.
[-]inconsistent wide character parameter handling in 64-bit python[/-][+]wide character parameter handling in ctypes[/+]jaraco commentedon Feb 2, 2009
I see this in the documentation, which basically answers the question:
"windll does not try to select [wide or narrow functions] by magic, you
must access the version you need by specifying GetModuleHandleA or
GetModuleHandleW explicitely, and then call it with normal strings or
unicode strings respectively."
This behavior is inconsistent with how structures are handled, where
members are up-converted to unicode. For example.
amauryfa commentedon Feb 3, 2009
ctypes cannot guess the function signature, and does not know if the function
expects strings or unicodes.
In your examples,
ctypes.windll.user32.MessageBoxW(handle, text, caption, type)
will accept everything you pass, and create C values depending on the types of the
actual values of the parameters: when you pass a unicode, ctypes uses a wchar_t*
buffer; when you pass a narrow string, ctypes uses a char* buffer (and is wrong in
this case).
In your Structure example, you do declare a kind of signature for the Structure.
ctypes is now able to convert the value you give into the declared type.
You can do the same thing with functions, if you provide the signature:
And then you may indifferently pass strings or unicodes:
MessageBox(None, u"café", "drink", 0)
jaraco commentedon Feb 3, 2009
Thanks for the excellent suggestion.
Please close this issue.