1

序文: 私は Python にかなり精通していますが、1 週間前まで C に触れたことがありませんでした... 今、ctypes を使用してモーター コントローラーに話しかけようとしています。

そのため、この特定の関数 (VCS_GetProtocolStackSettings) をいじっていましたが、つい最近まで動作させることができませんでした。私の問題は、「1」を返していますが (つまり、以下の仕様では成功しています)、戻りパラメーターにアクセスできないようです。

これが私のコードです。uint32 オブジェクトへのポインターに戻りパラメーターを格納していることがわかりますが、それらを取得する方法がわかりません。

lib=ctypes.WinDLL('C:\\Program Files (x86)\\maxon motor ag\\EPOS Positioning Controller\\EPOS2\\04 Programming\\Windows DLL\\EposCmd64.dll')

typeDict={  'char': ctypes.c_char,
        'char*': ctypes.c_char_p,
        '__int8': ctypes.c_int8,
        'BYTE': ctypes.c_uint8,
        'short': ctypes.c_int16,
        'WORD': ctypes.c_uint16,
        'long': ctypes.c_int32,
        'DWORD': ctypes.c_uint32,
        'BOOL': ctypes.c_int32,
        'HANDLE': ctypes.POINTER(ctypes.c_uint32)
        }

def VCS_GetProtocolStackSettings(KeyHandle):
    '''Returns the communication parameters 'baudrate and 
        'timeout'
    '''

    func=lib['VCS_GetProtocolStackSettings']
    func.argtypes
    func.restype=typeDict['BOOL']   

    pBaudrate=ctypes.pointer(typeDict['DWORD']())
    pTimeout=ctypes.pointer(typeDict['DWORD']())
    pErrorCode=ctypes.pointer(typeDict['DWORD']())

    cKeyHandle=typeDict['HANDLE'](KeyHandle)

    return func(KeyHandle,pBaudrate,pTimeout,pErrorCode)

ここに画像の説明を入力

4

2 に答える 2

2

pBaudrate.contents.valueポインターの値にアクセスしますが、本当に必要なのは a だけc_uint()で、参照によって関数に渡します。以下は例です。これは、失敗時に例外をスローすることにより、関数をより「Pythonic」にする例でもあります。

import ctypes
from ctypes import wintypes

lib = ctypes.WinDLL(dllnamehere)
lib.VCS_GetProtocolStackSettings.argtypes = [wintypes.HANDLE,wintypes.PDWORD,wintypes.PDWORD,wintypes.PDWORD]
lib.VCS_GetProtocolStackSettings.restype = wintypes.BOOL

def VCS_GetProtocolStackSettings(KeyHandle):
    baudrate = wintypes.DWORD()
    timeout = wintypes.DWORD()
    errorcode = wintypes.DWORD()
    result = lib.VCS_GetProtocolStackSettings(KeyHandle,ctypes.byref(baudrate),ctypes.byref(timeout),ctypes.byref(errorcode))
    if not result:
        raise RuntimeError('error code = {}'.format(errorcode.value))
    return baudrate.value,timeout.value

PSWinDLL適切であることを再確認してください。Windows システム DLL は__stdcall呼び出し規約を使用しますが、多くの DLL は__cdecl呼び出し規約を使用するため、CDLL代わりに使用します。

于 2013-01-19T20:35:31.283 に答える
1

ctypes をテストする場合は、ダミーの DLL を作成することをお勧めします。たとえば、関数のプロトタイプは次のとおりです (ここで見つけました)。

     Initialisation_DllExport BOOL __stdcall VCS_GetProtocolStackSettings(HANDLE KeyHandle, DWORD* pBaudrate, DWORD* pTimeout, DWORD* pErrorCode); 

ダミー DLL は次のようになります。

/**
 * file : lib.c
 * build: cl /LD lib.c
 */
#include <windows.h>
#include <stdio.h>
#define DLL_EXPORT __declspec(dllexport)

#ifdef __cplusplus
extern "C" {
#endif
DLL_EXPORT BOOL __stdcall VCS_GetProtocolStackSettings(HANDLE KeyHandle,
                                                       DWORD* pBaudrate,
                                                       DWORD* pTimeout,
                                                       DWORD* pErrorCode);
#ifdef __cplusplus
};
#endif

DLL_EXPORT BOOL __stdcall VCS_GetProtocolStackSettings(HANDLE KeyHandle,
                                                       DWORD* pBaudrate,
                                                       DWORD* pTimeout,
                                                       DWORD* pErrorCode)
{
    printf("%lu\n", (unsigned long) KeyHandle);
    *pBaudrate  = 1;
    *pTimeout   = 2;
    *pErrorCode = 3;

    return 4;
}

したがって、Python コードは次のようになります。

#!python

from ctypes import *

BOOL   = c_int
DWORD  = c_ulong
HANDLE = c_void_p

lib = WinDLL('./lib.dll')

# BOOL __stdcall VCS_GetProtocolStackSettings(HANDLE KeyHandle,
#                                             DWORD* pBaudrate,
#                                             DWORD* pTimeout,
#                                             DWORD* pErrorCode);

VCS_GetProtocolStackSettings = lib['VCS_GetProtocolStackSettings']
VCS_GetProtocolStackSettings.restype  = BOOL
VCS_GetProtocolStackSettings.argtypes = [HANDLE,
                                         POINTER(DWORD),
                                         POINTER(DWORD),
                                         POINTER(DWORD)]

KeyHandle = HANDLE(123)
Baudrate  = DWORD(0)
Timeout   = DWORD(0)
ErrorCode = DWORD(0)

result = BOOL(VCS_GetProtocolStackSettings(KeyHandle,
                                           byref(Baudrate),
                                           byref(Timeout),
                                           byref(ErrorCode)))

print(Baudrate.value)
print(Timeout.value)
print(ErrorCode.value)
print(result.value)

実行する場合:

> python example.py
123
1
2
3
4
>
于 2013-01-19T21:09:37.407 に答える