Hi all,
here a short C example of a running wrapper. It aim’s to add further (damping) variables to the output of an existing DISCON.dll.
[code]/*
- compile with: gcc -shared -o DISCON_wrapper.dll DISCON_wrapper.c
*/
#include <stdio.h>
#include <string.h>
#include <windows.h>
/* header */
char DLLpath[MAX_PATH], DLLbase[MAX_PATH]; // full file path and folder
char CtrlPath[MAX_PATH], OutfilePath[MAX_PATH];
char Message[257];
typedef void (*DisconFunc)(float *avrSwap, int *aviFail, char *accInfile, char *avcOutname, char *avcMsg);
DisconFunc _DisconFunc;
HINSTANCE hInstLibrary;
// file I/O
FILE *fp, *ip;
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
/* entry-point function /
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
BOOL ret=FALSE;
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf(“Using DISCONwrapper…\n”);
/ aquire path of original DISCON.dll */
GetModuleFileName((HINSTANCE)&__ImageBase,DLLpath,sizeof(DLLpath)); // get path of current DLL
char Dir[MAX_PATH]; // temporary path variable
_splitpath( DLLpath, DLLbase, Dir, NULL, NULL );
strcat(DLLbase,Dir);
// set path of real controller
strcpy(CtrlPath, DLLbase);
strcpy(Dir, DLLbase); // generate input file path
strcat(Dir, "DISCON_wrapper.inp");
ip=fopen(Dir, "r"); // OR char CtrlName[MAX_PATH];
fscanf(ip,"%s",Dir); // read DISCON.dll name as string
fclose(ip);
strcat(CtrlPath,Dir);
// load dll of real controller
hInstLibrary = LoadLibrary(CtrlPath);
//Set message to blank
// memset(Message,’ ',257);
if (hInstLibrary)
{
// load real controller
printf("[DISCONwrapper] Loading controller %s...\n", Dir);
// get pointer to DISCON function within the DLL
_DisconFunc = (DisconFunc)GetProcAddress(hInstLibrary, "DISCON");
// for debugging
// strcpy(Message, DLLbase);
ret = TRUE;
}
else
{
char msg[MAX_PATH];
strcpy(msg,"[DISCONwrapper] Loading DLL from path failed: ");
strcat(msg, CtrlPath );
strcat(msg, "\n" );
printf(msg);
// aviFail[0] = -1;
ret = FALSE;
}
// prepare files
strcpy(OutfilePath,DLLbase);
strcat(OutfilePath,"avrSwap.txt");
fp=fopen(OutfilePath, "w");
//Return strings
// memcpy(avcMsg,Message,MIN(256,NINT(avrSwap[48])));
break;
// case DLL_THREAD_ATTACH:
// printf(“DLL_THREAD_ATTACH”);
// break;
case DLL_PROCESS_DETACH:
printf("[DISCONwrapper] Finished run.\n");
FreeLibrary(hInstLibrary);
fclose(fp);
break;
}
return ret;
}
//Main DLL routine
void __declspec(dllexport) __cdecl DISCON(float *avrSwap, int *aviFail,
char *accInfile, char *avcOutname, char avcMsg)
{
// get current working dir for DISCON.IN — not needed for FAST
// char cwd;
// cwd = _getcwd( NULL, 0 );
// // add full path to accInfile
// strcat(cwd,“\DISCON.IN”);
// strcpy(accInfile,cwd);
/* 12:= demanded power
* 13:= shaft power
* 14:= electrical output
* 18:= Demanded generator speed above rated (rad/s)
* 19:= Measured generator speed (rad/s))
* 21:= Demanded generator torque (Nm)
* 22:= Measured generator torque (Nm) (GenTrq_prev)
*
* OUTPUTS
* 46:= Demanded generator torque (Nm)
*/
/* add calculations for drive-train damper here
* computedPower = [...]
*/
avrSwap[14] = computedPower;
_DisconFunc(avrSwap, aviFail, accInfile, avcOutname, avcMsg);
return;
}
[/code]
There are some changes of the file pathes, but in principial the original DISCON.dll location is read from the DISON_wrapper.inp input file, loaded at the initiation of the wrapper and then all inputs and outputs are handed over.
Regards, Sönke