在其他 class 中更改 c_ulong() 的值
Change value of c_ulong() in other class
我有一个文件 ConnectToBoard.dll 用于与硬件通信,在我的测试框架中,我编写了一个包装器用于从框架到设备的发送命令。
我需要为这个包装器创建一个单元测试,它将使用没有物理硬件的 ConnectToBoard.dll - 我在 python 中创建了一个 class,它将是 return 与 return ConnectToBoard.dll 相同的值,但没有此库的逻辑代码(只是硬编码值)。例如:
wrapper_framework.py
class WrapperFramework():
def __init__(self, test_mode=False):
self.dll = WinDLL(ConnectToBoard.dll)
if test_mode:
self.dll = MockForConnectToBoard()
def open_com_port(self):
return self.dll.OpenComPort()
dll 中的方法将查找空闲的 com 端口和 return 字符串中的名称端口。在我的单元测试中,我想创建这样的东西:
unittest.py
import pytest
@pytest.fixture
def setup_wrapper()
return WrapperFramework(test_mode=True)
@pytest.mark.usefixtures('setup_wrapper')
class TestMain:
def test_open_com_port():
assert setup_wrapper.dll.open_com_port == 'COM1'
mock_for_connect_to_board.py
class MockForConnectToBoard()
def OpenComPort():
return 'COM1'
但是我的模拟在 python 中的 ctypes 有问题。我不知道在这种情况下我应该怎么做:
wrapper_framework.py
def get_version_connect_to_board(self):
major = c_ulong()
minor = c_ulong()
build = c_ulong()
self.dll.GetVersionConnectToBoard(byref(major), byref(minor), byref(build))
return f'{major.value}.{minor.value}.{build.value}'
unittest.py
major = c_ulong()
minor = c_ulong()
build = c_ulong()
setup_wrapper.dll.GetVersionConnectToBoard(byref(major), byref(minor), byref(build))
assert major.value == 1
assert minor.value == 1
assert build.value == 1
(是的,它适用于没有测试模式和物理设备的普通 .dll)
现在:我不知道应该如何在我的模拟中编写方法 GetVersionConnectToBoard。我试过这样的东西:
mock_for_connect_to_board.py
def GetVersionConnectToBoard(self, major, minor, build):
major.value = 1
minor.value = 1
build.value = 1
return major, minor, build
但是我有错误:
AttributeError: 'CArgObject' object has no attribute 'value'
我检查了两个变量的类型 - 主修 wrapper_framework.py,它是:
<class 'ctypes.c_ulong'>
但在mock_for_connect_to_board.py中是
<class 'CArgObject'>
如何更改 major、minor 和 build in mock 的值?也许比创建模拟更好的方法?
major = c_ulong()
minor = c_ulong()
build = c_ulong()
setup_wrapper.dll.GetVersionConnectToBoard(byref(major), byref(minor), byref(build))
这是因为 ctypes.byref
创建了一个 CArgObject
实例,您无法从中获取值:它只能传递给 C 函数。
示例:
def foo(param):
print(param)
i = ctypes.c_int32(42)
foo(ctypes.byref(i))
这将打印:
<cparam 'P' (00000266E652E490)> <class 'CArgObject'>
幸运的是你可以使用ctypes.pointer
(注意:小写 pointer
不要与ctypes .POINTER
混淆)来实现你想要的。
示例:
def foo(param):
print(param, type(param))
print(param.contents.value)
# note: you can also change the value here
# param.contents.value = 12
i = ctypes.c_int32(42)
foo(ctypes.pointer(i))
输出:
<__main__.LP_c_long object at 0x000001CD108EE848> <class '__main__.LP_c_long'>
42
请注意,您可以使用 param.contents.value
.
访问参数值
如果我没记错的话,您的代码应该适用于以下内容:
major = c_ulong()
minor = c_ulong()
build = c_ulong()
setup_wrapper.dll.GetVersionConnectToBoard(ctypes.pointer(major), ctypes.pointer(minor), ctypes.pointer(build))
我有一个文件 ConnectToBoard.dll 用于与硬件通信,在我的测试框架中,我编写了一个包装器用于从框架到设备的发送命令。
我需要为这个包装器创建一个单元测试,它将使用没有物理硬件的 ConnectToBoard.dll - 我在 python 中创建了一个 class,它将是 return 与 return ConnectToBoard.dll 相同的值,但没有此库的逻辑代码(只是硬编码值)。例如:
wrapper_framework.py
class WrapperFramework():
def __init__(self, test_mode=False):
self.dll = WinDLL(ConnectToBoard.dll)
if test_mode:
self.dll = MockForConnectToBoard()
def open_com_port(self):
return self.dll.OpenComPort()
dll 中的方法将查找空闲的 com 端口和 return 字符串中的名称端口。在我的单元测试中,我想创建这样的东西:
unittest.py
import pytest
@pytest.fixture
def setup_wrapper()
return WrapperFramework(test_mode=True)
@pytest.mark.usefixtures('setup_wrapper')
class TestMain:
def test_open_com_port():
assert setup_wrapper.dll.open_com_port == 'COM1'
mock_for_connect_to_board.py
class MockForConnectToBoard()
def OpenComPort():
return 'COM1'
但是我的模拟在 python 中的 ctypes 有问题。我不知道在这种情况下我应该怎么做: wrapper_framework.py
def get_version_connect_to_board(self):
major = c_ulong()
minor = c_ulong()
build = c_ulong()
self.dll.GetVersionConnectToBoard(byref(major), byref(minor), byref(build))
return f'{major.value}.{minor.value}.{build.value}'
unittest.py
major = c_ulong()
minor = c_ulong()
build = c_ulong()
setup_wrapper.dll.GetVersionConnectToBoard(byref(major), byref(minor), byref(build))
assert major.value == 1
assert minor.value == 1
assert build.value == 1
(是的,它适用于没有测试模式和物理设备的普通 .dll) 现在:我不知道应该如何在我的模拟中编写方法 GetVersionConnectToBoard。我试过这样的东西:
mock_for_connect_to_board.py
def GetVersionConnectToBoard(self, major, minor, build):
major.value = 1
minor.value = 1
build.value = 1
return major, minor, build
但是我有错误:
AttributeError: 'CArgObject' object has no attribute 'value'
我检查了两个变量的类型 - 主修 wrapper_framework.py,它是:
<class 'ctypes.c_ulong'>
但在mock_for_connect_to_board.py中是
<class 'CArgObject'>
如何更改 major、minor 和 build in mock 的值?也许比创建模拟更好的方法?
major = c_ulong()
minor = c_ulong()
build = c_ulong()
setup_wrapper.dll.GetVersionConnectToBoard(byref(major), byref(minor), byref(build))
这是因为 ctypes.byref
创建了一个 CArgObject
实例,您无法从中获取值:它只能传递给 C 函数。
示例:
def foo(param):
print(param)
i = ctypes.c_int32(42)
foo(ctypes.byref(i))
这将打印:
<cparam 'P' (00000266E652E490)> <class 'CArgObject'>
幸运的是你可以使用ctypes.pointer
(注意:小写 pointer
不要与ctypes .POINTER
混淆)来实现你想要的。
示例:
def foo(param):
print(param, type(param))
print(param.contents.value)
# note: you can also change the value here
# param.contents.value = 12
i = ctypes.c_int32(42)
foo(ctypes.pointer(i))
输出:
<__main__.LP_c_long object at 0x000001CD108EE848> <class '__main__.LP_c_long'>
42
请注意,您可以使用 param.contents.value
.
如果我没记错的话,您的代码应该适用于以下内容:
major = c_ulong()
minor = c_ulong()
build = c_ulong()
setup_wrapper.dll.GetVersionConnectToBoard(ctypes.pointer(major), ctypes.pointer(minor), ctypes.pointer(build))