Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调用Windows DLL的python不可知代码_Python_Python 3.x_Windows_Dll_Python 2.x - Fatal编程技术网

调用Windows DLL的python不可知代码

调用Windows DLL的python不可知代码,python,python-3.x,windows,dll,python-2.x,Python,Python 3.x,Windows,Dll,Python 2.x,我所要做的就是想出一个与python无关的调用Windows DLL的代码。我所说的python不可知论是指我希望它在python 2、python 3、cygwin CPython和Windows CPython中都能同样出色地工作。最后,我还希望它也能在Jython和IronPython中工作,以及在MSYS2中工作 我读过吴永伟关于MSVC和MinGW的Stdcall和DLL工具的非常好的文章,以及其他几篇stackoverflow文章——我的目标似乎并不那么普遍 经过反复试验,我提出了两

我所要做的就是想出一个与python无关的调用Windows DLL的代码。我所说的python不可知论是指我希望它在python 2、python 3、cygwin CPython和Windows CPython中都能同样出色地工作。最后,我还希望它也能在Jython和IronPython中工作,以及在MSYS2中工作

我读过吴永伟关于MSVC和MinGW的Stdcall和DLL工具的非常好的文章,以及其他几篇stackoverflow文章——我的目标似乎并不那么普遍

经过反复试验,我提出了两个似乎可行的想法,但我不确定它们是否真的解决了吴永伟文章中涉及的“呼叫约定”ABI问题

在Python 2和3以及Cygwin CPython和Windows CPython中,第一种工作方式是:

import os, sys, platform, re
'''Make Wide'''
def makeWide(instring):
    outstring=''
    python_version_int = sys.version_info.major * 1000000 + sys.version_info.minor * 1000 +  sys.version_info.micro
    for idx in range(0,len(instring)):
        if python_version_int < 3000000:
            outstring=outstring+instring[idx:idx+1]+chr(0)
        else:
            outstring=outstring+instring[idx:idx+1]
    return outstring
python_platform_short=re.sub(r"_.*$","", platform.system() , 1 ).lower();
Windows_System32_User32_DLL_win = 'C:/Windows/System32/User32.dll'
Windows_System32_User32_DLL_cyg = '/cygdrive/c/Windows/System32/User32.dll'
MB_ABORTRETRYIGNORE = c_long(2)
Windows_System32_User32_DLL = Windows_System32_User32_DLL_win
if python_platform_short == 'cygwin':
    Windows_System32_User32_DLL = Windows_System32_User32_DLL_cyg
if python_platform_short == 'cygwin':
    user32=cdll.LoadLibrary(Windows_System32_User32_DLL)
else:
    user32=windll.LoadLibrary(Windows_System32_User32_DLL)
user32_MessageBoxW=getattr(user32,"MessageBoxW")
message_box_window  = c_void_p(0)  # HWND
message_box_title   = c_wchar_p('Hello')
message_box_message = c_wchar_p('Hello world!!')
message_box_flags   = MB_ABORTRETRYIGNORE
user32_MessageBoxW(message_box_window, message_box_message, message_box_title, message_box_flags )

这尝试使用六和和编码(“utf-16LE”)来解决Python2和Python3中的字符串差异,并使用cffi调用dll。同样,我不太清楚这是否解决了堆栈问题

第三种可以让我直接解决ABI和堆栈问题的方法是使用pycca深入到汇编,但我还没有学到足够的x86汇编来尝试这一点——尽管我已经阅读了有关调用约定的nasm文档和相关的wikipedia文章。我认为我将能够让Jython使用JNA工作,但我仍在学习IronPython和相关的python包

有人能帮我使用cffi、ctypes或Pyca方法吗?对IronPython或Jython有什么建议吗


from cffi import FFI
import six
class Win:
    def message_box(self, hwnd, lptext, lpcaption, utype):
        ffi = FFI()
        cdefStr="""
        int __stdcall MessageBoxW(void *    hWnd,  const char16_t *    lpText, const char16_t *    lpCaption,  unsigned int     uType);
        """
        print("DEBUG : cdefStr = " + cdefStr )
        ffi.cdef( cdefStr );
        user32 = ffi.dlopen('C:\\Windows\\System32\\user32.dll')
        if( hwnd == 0 ):
            hwnd=ffi.NULL;
        textSize=len(lpcaption)
        lpcapForCType = "const char16_t[" + str(textSize+2) + "]"
        lpcapForC = ffi.new( lpcapForCType )
        for i in range( 0 , textSize ):
            lpcapForC[i]    = six.unichr(   six.indexbytes( six.ensure_binary( lpcaption.encode("utf-16LE") ) ,(i*2)) + 256 * six.indexbytes( six.ensure_binary( lpcaption.encode("utf-16LE") ) ,(i*2)+1)    )
        lpcapForC[textSize] = six.unichr(0)
        textSize=len(lptext)
        lptextForC = ffi.new("const char16_t[" + str( textSize + 2 ) + "]" )
        for i in range(0,textSize):
            lptextForC[i]   = six.unichr(   six.indexbytes( six.ensure_binary( lptext.encode("utf-16LE")    ) ,(i*2)) + 256 * six.indexbytes( six.ensure_binary( lptext.encode("utf-16LE")    ) ,(i*2)+1)    )
        lpcapForC[textSize] = six.unichr(0)
        utype=ffi.cast("unsigned int",utype);
        user32.MessageBoxW(hwnd, lptextForC, lpcapForC, utype)
msg = six.u("Test with umlaut: ") + six.unichr(0xe4)
w = Win()
w.message_box(0, msg, msg, 0)