2015-11-04 61 views
4

我有一个需要进行单元测试的TI处理器的嵌入式C语言版本。
对于目标编译使用IAR,但我使用MinGW GCC在Win7机器上运行测试。如何在单元测试时重置状态机C

在C代码中,有些函数包含有时需要在测试之间重置的状态机。这些状态机通常将状态变量保持在本地静态,这使得这个任务即使不是不可能也很困难

我不是很了解C++类,但是我有一个关于将C函数“导入”包装C++类的想法,因为memberfunctions使得只要需要重置就可以创建一个新对象。下面的代码是非功能性的,但它说明了我的想法。

在main.cpp中

#include "statemachine.h" 

    using namespace std; 

    class stateMachineWrapper { 
    public: 
     extern void stateMachine(void); 
    }; 

    int main() { 
     stateMachineWrapper myObject; 

     myObject.stateMachine(); 

     myObject.stateMachine(); 

     stateMachineWrapper myNewObject; 

     myNewObject.stateMachine(); 

     myNewObject.stateMachine(); 

     return 0; 
    } 

在statemachine.h:

void stateMachine(void); 

在statemachine.c:

#include <stdio.h> 

    void stateMachine(void) 
    { 
     static int myState = 0; 

     switch(myState) 
     { 
     case 0: 
     { 
     printf("Init State"); 
     myState = 1; 
     break; 
     } 
     case 1: 
     { 
     printf("Second state"); 
     break; 
     } 
     default: 
     { 
     printf("Default"); 
     break; 
     } 
     } 
    } 

改建的statemachine.c/.H是不鼓励,因为它可以被视为“遗产”。
当然也欢迎任何其他解决方案!

回答

1

@unwind发给我看动态代码加载!
读这些: Dynamically load a function from a DLLhttp://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/给了我足够的调制下面的解决方案。

在statemachine.h

void stateMachine(void); 

在statemachine.c:

#include <stdio.h> 

    void stateMachine(void) 
    { 
     static int myState = 0; 

     switch(myState) 
     { 
     case 0: 
     { 
     printf("Init State"); 
     myState = 1; 
     break; 
     } 
     case 1: 
     { 
     printf("Second state"); 
     break; 
     } 
     default: 
     { 
     printf("Default"); 
     break; 
     } 
     } 
    } 

在statemachinelib.c:

#include "statemachine.h" 

    __declspec(dllexport) void __cdecl statemachineWrap() 
    { 
     stateMachine(); 
    } 

main.c中:

#include <windows.h> 
    #include <stdlib.h> 
    #include <stdio.h> 

    typedef int (__stdcall *f_funci)(); 

    int main(int argc, char **argv) 
    { 
     HINSTANCE hGetProcIDDLL = LoadLibrary("statemachinelib.dll"); 

     f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "statemachineWrap"); 

     funci(); 

     funci(); 

     funci(); 

     FreeLibrary(hGetProcIDDLL); //Windows detects that no one is using this library anymore and unloads it from memory, giving the new LoadLibrary a fresh instance 

     hGetProcIDDLL = LoadLibrary("statemachinelib.dll"); 

     funci = (f_funci)GetProcAddress(hGetProcIDDLL, "statemachineWrap"); 

     funci(); 

     funci(); 

     funci(); 

     return 0; 
    } 

在这段代码中,我省略了很多安全语句,例如检查DLL是否可以加载,如果找到函数,是否想要dllexport或dllimport等,以便更容易掌握正在发生的事情。如果你打算在任何真正的项目中实现这一点,你至少应该阅读上面提到的两个资源。该DLL的

编译使用MinGW的:

>gcc -c statemachine.c statemachinelib.c 
>gcc -o statemachinelib.dll -s -shared statemachinelib.o statemachine.o -Wl,--subsystem,windows 

编译可执行的,也MinGW的:

>gcc -o main.exe main.c 

执行率:

>main.exe 
Init State 
Second state 
Second state 
Init State 
Second state 
Second state 

我就离开这个在这里几天,如果没有人反对,我会将其标记为我接受的答案!

编辑:我已经阐述了一下,这里有一个从我一个(解决)问题只是一个轻微的调整Exporting a function, cast into a pointer through a DLL

2

包装将无济于事。 C++代码没有办法达到写入C.

的一个解决方案的状态机内的内部static变量的是使用动态代码加载为C的部分,这将使早期初始化代码,并清除static变量。您也可以将测试分成多个可执行文件,它们具有相同的效果,但可能会有更大的开销(=测试运行速度会更慢)。

+0

什么,我希望能实现没有访问到'static'变量,而是一个办法创建一个新的Statemachine新实例。 是的,多位高级管理人员对我来说是如此,但是正如你所说的那样,要花费额外的时间而不是仅仅对新对象执行另一次运行。 – Enok82

+0

@ Enok82但是这种C代码没有“实例”的概念。全局变量永远是一个全局变量。它将由启动代码初始化(在'main()'在普通程序中运行之前),并且不能在以后再次调用。 – unwind

+0

成功......您的指向动态代码加载的指示向我发送了一条导致相当有用的路径。我会在一两分钟内发布我的解决方案!谢谢! – Enok82