前言:我对Python非常熟悉,但直到一周前从未接触过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)
答案 0 :(得分:2)
pBaudrate.contents.value
将访问指针中的值,但您只需要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
P.S。仔细检查WinDLL
是否合适。 Windows系统DLL使用__stdcall
调用约定,但许多DLL使用__cdecl
调用约定,而您将使用CDLL
代替。
答案 1 :(得分:1)
如果正在测试ctypes,最好制作一个虚拟DLL。例如,函数的原型是(我发现它here):
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
>