2015-06-11 25 views
1

我在Windows 7/64上使用winpython(2.7),matlab 2015a,使用matlab新的python bridge如何在windows上使用msvc * .dll的ctypes

>> py.ctypes.util.find_library('c') 

ans = 

    Python str with no properties. 

    msvcr90.dll 

>> py.ctypes.util.find_msvcrt() 

ans = 

    Python str with no properties. 

    msvcr90.dll 

>> py.ctypes.CDLL(py.ctypes.util.find_library('c')) 
Python Error: [Error 1114] A dynamic link library (DLL) initialization routine failed 

>> x=CDLL('C:\Users\nlab\Downloads\WinPython-64bit-2.7.9.5\python-2.7.9.amd64\msvcr90.dll') 
Python Error: [Error 1114] A dynamic link library (DLL) initialization routine failed 

的彈出也出現:

Microsoft Visual C++ Runtime Library 
R6034 "an application has made an attempt to load the c runtime library incorrectly" 

一個couple otherSO answers表明,它是MATLAB把MSVC其不兼容副本的* .dll某處的道路上,所以我在sys去除一切不是從WinPython。路徑(只是MATLAB的\bin\win64\\Python27\site-packages\從另一個Python安裝我有):

>> py.pprint.PrettyPrinter().pprint(py.sys.path) 
['', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\python27.zip', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\DLLs', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib\\plat-win', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib\\lib-tk', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib\\site-packages', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib\\site-packages\\FontTools', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib\\site-packages\\win32', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib\\site-packages\\win32\\lib', 
'C:\\Users\\nlab\\Downloads\\WinPython-64bit-2.7.9.5\\python-2.7.9.amd64\\lib\\site-packages\\Pythonwin'] 

仍有ŧ MSVC的組件* .DLL到處灑在系統上,並肯定了一些對PATH:

>> x = py.os.environ 

x = 

    Python _Environ with properties: 

    data: [1x1 py.dict] 

    {'TMP': 'C:\\Users\\nlab\\AppData\\Local\\Temp', <<snip>>, 'USERPROFILE': 'C:\\Users\\nlab'} 

>> cellfun(@(s)fprintf('%s\n',s),strsplit(char(x{'PATH'}),';')) 
C:\Program Files\Haskell\bin 
C:\Program Files\Haskell Platform\2014.2.0.0\lib\extralibs\bin 
C:\Program Files\Haskell Platform\2014.2.0.0\bin 
C:\Users\nlab\Downloads\WinPython-64bit-2.7.9.5\python-2.7.9.amd64 
C:\Users\nlab\Downloads\opencv\build\x64\vc12\bin 
C:\ProgramData\Oracle\Java\javapath 
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\bin\ 
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\libnvvp\ 
C:\Program Files\ImageMagick-6.8.3-Q16 
C:\Program Files (x86)\OSSBuild\GStreamer\v0.10.7\bin 
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.1\\bin 
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v4.1\libnvvp\ 
C:\Program Files (x86)\PHP\ 
C:\Windows\system32 
C:\Windows 
C:\Windows\System32\Wbem 
C:\Program Files\Intel\DMIX 
C:\Program Files\TortoiseSVN\bin 
C:\Program Files\SlikSvn\bin\ 
C:\Program Files\MySQL\MySQL Server 5.5\bin 
C:\Program Files (x86)\Common Files\Acronis\SnapAPI\ 
C:\Program Files (x86)\PostgreSQL\9.2\bin 
C:\Python27 
C:\Python27\Scripts 
C:\Program Files\Microsoft SQL Server\110\Tools\Binn\ 
C:\Windows\System32\WindowsPowerShell\v1.0\ 
C:\Program Files (x86)\LilyPond\usr\bin 
C:\Program Files (x86)\Git\cmd 
C:\Program Files\Microsoft Windows Performance Toolkit\ 
C:\Program Files\TortoiseGit\bin 
C:\Program Files (x86)\QuickTime\QTSystem\ 
C:\Program Files (x86)\Skype\Phone\ 
C:\Program Files\Mosek\7\tools\platform\win64x86\bin 
C:\Program Files\Haskell Platform\2014.2.0.0\mingw\bin 
C:\Users\nlab\AppData\Roaming\cabal\bin 
C:\Program Files (x86)\SSH Communications Security\SSH Secure Shell 
C:\Gtk+\bin 

我注意到,在C:\Program Files\MATLAB\R2015a\bin\win64\我們只有msvc[r|p][100|110].dll - 這是否意味着它不會與蟒蛇的發行工作基於msvcr90像winpython 2.7.9.5?

+3

msvcr90.dll的初始化調用'FindActCtxSectionString'在當前激活上下文中查找「msvcr90.dll」。如果此調用失敗,則卸載它,返回'FALSE',並且加載程序報告初始化失敗。通常,對於Python 2.7,此激活上下文由嵌入在python.exe中的清單提供。但是,您也可以在運行時修改激活上下文。請參閱我的答案[如何從Python中的SXS加載C DLL?](http://stackoverflow.com/a/27392347/205580)。 – eryksun

+0

謝謝@eryksun,看起來很有希望。但我並不熟悉這些東西,你能給我一些背景嗎?就像我想指向python的matlab的msvcr或v/v,爲什麼他們每個人都不滿意自己的?其中一個使用msvcr會不會有危險?我的清單應該是什麼樣子?你的.py代碼不需要改變,對吧?我真的想從matlab中得到體面的工作,他們的安裝非常複雜,所以我不能真正編輯他們的cdll調用 - https://github.com/Toblerity/Shapely/blob/master/shapely/libgeos.py – user1441998

+0

顯然我必須使用matlab的 - 用'CDLL('C:\\ Program Files \\ MATLAB \\ R2015a \\ bin \\ win64 \\ msvcr100.dll')來代替勻稱的CDLL(find_library('c')) )'使得所有的工作 - 所以@eryksun,如果我明白,你的方法將是一種方法來確定自動使用正確的路徑? – user1441998

回答

0

定義了這個文件msvc.py

import ctypes 
print ctypes.cdll.msvcrt 
在MATLAB

則:

>> py.importlib.import_module('msvc') 
<CDLL 'msvcrt', handle fe190000 at 771c2b38> 

ans = 

    Python module with properties: 

    ctypes: [1x1 py.module] 

    <module 'msvc' from 'msvc.pyc'> 

>> x = py.ctypes.cdll 

x = 

    Python LibraryLoader with properties: 

    msvcrt: [1x1 py.ctypes.CDLL] 

    <ctypes.LibraryLoader object at 0x00000000771D6278> 

>> x.msvcrt 

ans = 

    Python CDLL with no properties. 

    <CDLL 'msvcrt', handle fe190000 at 771c2b38> 

我不知道爲什麼有必要使用msvc.py - 只導入​​不給你一個cdll與一個msvcrt財產。

+0

您的MATLAB接口無法處理'cdll'的動態'__getattr__'設計。你不能簡單地使用'msvcrt = py.ctypes.CDLL('msvcrt')'來加載DLL嗎? 'cdll'使用內建的'setattr'將自己的結果緩存到自己。 – eryksun

+0

that worked(more SOrs ...) – user1441998

0

@ eryksun的方法有效。

問題依然存在,爲什麼ctypes.cdll.msvcrtfind_library('c')以他們的方式實施?他們應該只使用@ersksun的方法在python的清單中返回dll,對吧?

from ctypes import * 
from ctypes.wintypes import * 

kernel32 = WinDLL("kernel32") 

ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID = 0x001 
ACTCTX_FLAG_LANGID_VALID = 0x002 
ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004 
ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x008 
ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x010 
ACTCTX_FLAG_APPLICATION_NAME_VALID = 0x020 
ACTCTX_FLAG_HMODULE_VALID = 0x080 
DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION = 1 

INVALID_HANDLE_VALUE = HANDLE(-1).value 
ULONG_PTR = WPARAM # pointer-sized unsigned integer 

class ACTCTX(Structure): 
    _fields_ = (("cbSize", ULONG), 
       ("dwFlags", DWORD), 
       ("lpSource", LPCWSTR), 
       ("wProcessorArchitecture", USHORT), 
       ("wLangId", LANGID), 
       ("lpAssemblyDirectory", LPCWSTR), 
       ("lpResourceName", LPCWSTR), 
       ("lpApplicationName", LPCWSTR), 
       ("hModule", HMODULE)) 

    def __init__(self, *args, **kwds): 
     super(ACTCTX, self).__init__(sizeof(self), *args, **kwds) 

CreateActCtxW = kernel32.CreateActCtxW 
CreateActCtxW.restype = HANDLE 
CreateActCtxW.argtypes = (POINTER(ACTCTX),) 
ReleaseActCtx = kernel32.ReleaseActCtx 
ReleaseActCtx.restype = None 
ReleaseActCtx.argtypes = (HANDLE,) 
ActivateActCtx = kernel32.ActivateActCtx 
ActivateActCtx.argtypes = (HANDLE, POINTER(ULONG_PTR)) 
DeactivateActCtx = kernel32.DeactivateActCtx 
DeactivateActCtx.argtypes = (DWORD, ULONG_PTR) 

def getMsvcr90(): 
    ctx = ACTCTX(hModule = cdll.python27._handle 
       ,lpResourceName = c_wchar_p(2) 
       ,dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID 
       ) 
    hActCtx = CreateActCtxW(byref(ctx)) 
    if hActCtx == INVALID_HANDLE_VALUE: 
     raise WinError() 

    cookie = ULONG_PTR() 
    if not ActivateActCtx(hActCtx, byref(cookie)): 
     raise WinError() 
    msvcr90 = CDLL("msvcr90") 
    if not DeactivateActCtx(0, cookie): 
     raise WinError() 

    ReleaseActCtx(hActCtx) 

    # show DLL path 
    hModule = HANDLE(msvcr90._handle) 
    path = (c_wchar * 260)()  
    kernel32.GetModuleFileNameW(hModule, path, len(path)) 
    print(path.value) 

    return msvcr90 
+0

即使'LoadLibraryW(u'msvcr90')'和'GetModuleHandleW(u'msvcr90')'不具備完全限定路徑或者激活上下文,如果你確實知道你的進程只有一個加載的實例/版本的msvcr90.dll,你可以調用'EnumProcessModules'來獲得一個模塊句柄數組,然後調用'GetModuleBaseNameW'來找到帶有基本名稱等於'u'msvcr90.dll''。然後,您可以將其包裝在CDLL實例中,例如'msvcr90 = CDLL('msvcr90',句柄= hModule)'。 – eryksun

+0

由於'_ctypes'擴展模塊直接暴露了一些CRT函數的地址,因此獲得CRT句柄的更可靠的方法是調用'GetModuleHandleExW'。例如:'import ctypes;''hMsvcr = ctypes.c_void_p();''GMHEXF_FROM_ADDRESS = 4;''ctypes.windll.kernel32.GetModuleHandleExW(GMHEXF_FROM_ADDRESS,ctypes.memset,ctypes.byref(hMsvcr));''msvcr = ctypes.CDLL('msvcr',handle = hMsvcr.value)' – eryksun

+0

如果您在使用動態'__getattr__'時遇到問題,請嘗試將該函數引用爲'ctypes.windll ['kernel32'] ['GetModuleHandleExW' ]'。 – eryksun

相關問題