Search code examples
pythonwinapictypesuser32

ToUnicodeEx() always returns 0 in python


I was trying to wrap C++ function ToUnicodeEx() in python, but it not works correctly, always returns 0.
On MSDN 0 means:

The specified virtual key has no translation for the current state of the keyboard. Nothing was written to the buffer specified by pwszBuff.

from ctypes import *
_ToUnicodeEx = WinDLL('user32').ToUnicodeEx
_ToUnicodeEx.argtypes = [c_uint,c_uint,c_byte,c_wchar_p,c_int,c_uint,c_int]
_ToUnicodeEx.restype = c_int
def ToUn(vk,sc,kst,wfl,hkid):
    #b - is as in C++ pwszBuff 
    b = create_unicode_buffer(5)
    print(_ToUnicodeEx(vk,sc,kst,b,5,wfl,hkid))
    return b.value
#It must print "a" but prints "".
print(ToUn(65,0,0,0,1033))

Does i done something wrong, that it always returns 0?
P.S. In C# worked, with same arguments...


Solution

  • This more closely matches the MSDN documentation for ToUnicodeEx:

    _ToUnicodeEx.argtypes = [c_uint,c_uint,POINTER(c_char),POINTER(c_wchar),c_int,c_uint,c_void_p]
    

    c_wchar_p assumes null termination and c_void_p is appropriate for a handle. The third parameter is supposed to be an 256-byte array and the last parameter is optional, so I tried this and got the result you want. I'll admit I don't understand the intricacies of the function so I don't know what is appropriate for parameters. I just met the type requirements.

    from ctypes import *
    _ToUnicodeEx = WinDLL('user32').ToUnicodeEx
    _ToUnicodeEx.argtypes = [c_uint,c_uint,POINTER(c_char),POINTER(c_wchar),c_int,c_uint,c_void_p]
    _ToUnicodeEx.restype = c_int
    def ToUn(vk,sc,wfl,hkid):
        kst = create_string_buffer(256)
        b = create_unicode_buffer(5)
        print(_ToUnicodeEx(vk,sc,kst,b,5,wfl,hkid))
        return b.value
    print(ToUn(65,0,0,None))
    

    Output:

    1
    a