在其他 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))