Reputation: 162
I have a se of embedded C for a TI processor that need to be unit tested.
For target compilation IAR is used but i am running the tests on a Win7 machine using MinGW GCC.
In the C code there are functions containing state machines that sometimes need to be reset between tests. These state machines often keep their state variable locally static, making that task difficult if not impossible.
I'm not very C++ class savvy but i had an idea about "importing" the C functions into a wrapping C++ class as memberfunctions making it possible to just create a new object whenever a reset i needed. The code below is non functional but it illustrates my idea.
in 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;
}
in statemachine.h:
void stateMachine(void);
in 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;
}
}
}
Alterations to the statemachine.c/.h is not encouraged since it can be considered "legacy".
Any other solutions is of course welcome as well!
Upvotes: 4
Views: 796
Reputation: 162
@unwind sent me looking at dynamic code loading!
Reading these:
Dynamically load a function from a DLL and http://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/ gave me enough to concoct the following solution.
in statemachine.h:
void stateMachine(void);
in 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;
}
}
}
in statemachinelib.c:
#include "statemachine.h"
__declspec(dllexport) void __cdecl statemachineWrap()
{
stateMachine();
}
in 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;
}
In this code i have omitted a lot of safety statements such as checking if the DLL could be loaded, if the function is found, whether we want too dllexport or dllimport and so on only to make it easier to grasp what is going on. If you are going to implement this in any real project you should at least read both of the resources i mentioned above.
compilation of the DLL using MinGW:
>gcc -c statemachine.c statemachinelib.c
>gcc -o statemachinelib.dll -s -shared statemachinelib.o statemachine.o -Wl,--subsystem,windows
compilation of the executable, also MinGW:
>gcc -o main.exe main.c
execution yields:
>main.exe
Init State
Second state
Second state
Init State
Second state
Second state
I'll just leave this here for a few days and if no one objects i will mark this as my accepted answer!
Edit: I have elaborated a bit and there's another (solved) question from me here with just a slight tweak Exporting a function, cast into a pointer through a DLL
Upvotes: 1
Reputation: 399753
The wrapping won't help. The C++ code has no way of reaching the internal static
variable inside the state machine written in C.
One solution is to use dynamic code loading for the C parts, that will make the early initialization code and clear the static
variable.
You could also split the tests into multiple executables, that has the same effect but probably larger overhead (=tests will run more slowly).
Upvotes: 2