/*Example of a CAPL DLL implementation */ #define USECDLL_FEATURE #define _BUILDNODELAYERDLL #pragma warning( disable : 4786 ) #include "..\Includes\cdll.h" #include "..\Includes\via.h" #include "..\Includes\via_CDLL.h" #include #include #include class CaplInstanceData; typedef std::map VCaplMap; typedef std::map VServiceMap; // ============================================================================ // global variables // ============================================================================ static unsigned long data = 0; static char dlldata[100]; char gModuleName[_MAX_FNAME]; // filename of this dll HINSTANCE gModuleHandle; // windows instance handle of this DLL VCaplMap gCaplMap; VServiceMap gServiceMap; // ============================================================================ // CaplInstanceData // // Data local for a single CAPL Block. // // A CAPL-DLL can be used by more than one CAPL-Block, so every piece of // information thats like a globale variable in CAPL, must now be wraped into // an instance of an object. // ============================================================================ class CaplInstanceData { public: CaplInstanceData(VIACapl* capl); void GetCallbackFunctions(); void ReleaseCallbackFunctions(); // Definition of the class function. // This class function will call the // CAPL callback functions uint32 ShowValue(uint32 x); uint32 ShowDates(int16 x, uint32 y, int16 z); void DllInfo(char* x); void ArrayValues(uint32 flags, uint32 numberOfDatabytes, uint8 databytes[], uint8 controlcode); void DllVersion(char* y); private: // Pointer of the CAPL callback functions VIACaplFunction* mShowValue; VIACaplFunction* mShowDates; VIACaplFunction* mDllInfo; VIACaplFunction* mArrayValues; VIACaplFunction* mDllVersion; VIACapl* mCapl; }; CaplInstanceData::CaplInstanceData(VIACapl* capl) // This function will initialize the CAPL callback function // with the NLL Pointer : mCapl(capl), mShowValue(NULL), mShowDates(NULL), mDllInfo(NULL), mArrayValues(NULL), mDllVersion(NULL) {} static bool sCheckParams(VIACaplFunction* f, char rtype, char* ptype) { char type; int32 pcount; VIAResult rc; // check return type rc = f->ResultType(&type); if (rc!=kVIA_OK || type!=rtype) { return false; } // check number of parameters rc = f->ParamCount(&pcount); if (rc!=kVIA_OK || strlen(ptype)!=pcount ) { return false; } // check type of parameters for (int i=0; iParamType(&type, i); if (rc!=kVIA_OK || type!=ptype[i]) { return false; } } return true; } static VIACaplFunction* sGetCaplFunc(VIACapl* capl, const char * fname, char rtype, char* ptype) { VIACaplFunction* f; // get capl function object VIAResult rc = capl->GetCaplFunction(&f, fname); if (rc!=kVIA_OK || f==NULL) { return NULL; } // check signature of function if ( sCheckParams(f, rtype, ptype) ) { return f; } else { capl->ReleaseCaplFunction(f); return NULL; } } void CaplInstanceData::GetCallbackFunctions() { // Get a CAPL function handle. The handle stays valid until end of // measurement or a call of ReleaseCaplFunction. mShowValue = sGetCaplFunc(mCapl, "CALLBACK_ShowValue", 'D', "D"); mShowDates = sGetCaplFunc(mCapl, "CALLBACK_ShowDates", 'D', "IDI"); mDllInfo = sGetCaplFunc(mCapl, "CALLBACK_DllInfo", 'V', "C"); mArrayValues = sGetCaplFunc(mCapl, "CALLBACK_ArrayValues", 'V', "DBB"); mDllVersion = sGetCaplFunc(mCapl, "CALLBACK_DllVersion", 'V', "C"); } void CaplInstanceData::ReleaseCallbackFunctions() { // Release all the requested Callback functions mCapl->ReleaseCaplFunction(mShowValue); mShowValue = NULL; mCapl->ReleaseCaplFunction(mShowDates); mShowDates = NULL; mCapl->ReleaseCaplFunction(mDllInfo); mDllInfo = NULL; mCapl->ReleaseCaplFunction(mArrayValues); mArrayValues = NULL; mCapl->ReleaseCaplFunction(mDllVersion); mDllVersion = NULL; } void CaplInstanceData::DllVersion(char* y) { // Prepare the parameters for the call stack of CAPL. // Arrays uses a 8 byte on the stack, 4 Bytes for the number of element, // and 4 bytes for the pointer to the array int32 sizeX = strlen(y)+1; uint8 params[8]; // parameters for call stack, 8 Bytes total memcpy(params+0, &sizeX, 4); // array size of first parameter, 4 Bytes memcpy(params+4, &y, 4); // array pointer of first parameter, 4 Bytes if(mDllVersion!=NULL) { uint32 result; // dummy variable VIAResult rc = mDllVersion->Call(&result, params); } } uint32 CaplInstanceData::ShowValue(uint32 x) { void* params = &x; // parameters for call stack uint32 result; if(mShowValue!=NULL) { VIAResult rc = mShowValue->Call(&result, params); if (rc==kVIA_OK) { return result; } } return -1; } uint32 CaplInstanceData::ShowDates(int16 x, uint32 y, int16 z) { // Prepare the parameters for the call stack of CAPL. The stack grows // from top to down, so the first parameter in the parameter list is the last // one in memory. CAPL uses also a 32 bit alignment for the parameters. uint8 params[12]; // parameters for call stack, 12 Bytes total memcpy(params+0, &z, 2); // third parameter, offset 0, 2 Bytes memcpy(params+4, &y, 4); // second parameter, offset 4, 4 Bytes memcpy(params+8, &x, 2); // first parameter, offset 8, 2 Bytes uint32 result; if(mShowDates!=NULL) { VIAResult rc = mShowDates->Call(&result, params); if (rc==kVIA_OK) { return rc; // call successful } } return -1; // call failed } void CaplInstanceData::DllInfo(char* x) { // Prepare the parameters for the call stack of CAPL. // Arrays uses a 8 byte on the stack, 4 Bytes for the number of element, // and 4 bytes for the pointer to the array int32 sizeX = strlen(x)+1; uint8 params[8]; // parameters for call stack, 8 Bytes total memcpy(params+0, &sizeX, 4); // array size of first parameter, 4 Bytes memcpy(params+4, &x, 4); // array pointer of first parameter, 4 Bytes if(mDllInfo!=NULL) { uint32 result; // dummy variable VIAResult rc = mDllInfo->Call(&result, params); } } void CaplInstanceData::ArrayValues(uint32 flags, uint32 numberOfDatabytes, uint8 databytes[], uint8 controlcode) { // Prepare the parameters for the call stack of CAPL. The stack grows // from top to down, so the first parameter in the parameter list is the last // one in memory. CAPL uses also a 32 bit alignment for the parameters. // Arrays uses a 8 byte on the stack, 4 Bytes for the number of element, // and 4 bytes for the pointer to the array uint8 params[16]; // parameters for call stack, 16 Bytes total memcpy(params+ 0, &controlcode, 1); // third parameter, offset 0, 1 Bytes memcpy(params+ 4, &numberOfDatabytes, 4); // second parameter (array size), offset 4, 4 Bytes memcpy(params+ 8, &databytes, 4); // second parameter (array pointer), offset 8, 4 Bytes memcpy(params+12, &flags, 4); // first parameter, offset 12, 4 Bytes if(mArrayValues!=NULL) { uint32 result; // dummy variable VIAResult rc = mArrayValues ->Call(&result, params); } } CaplInstanceData* GetCaplInstanceData(uint32 handle) { VCaplMap::iterator lSearchResult(gCaplMap.find(handle)); if ( gCaplMap.end()==lSearchResult ) { return NULL; } else { return lSearchResult->second; } } // ============================================================================ // CaplInstanceData // // Data local for a single CAPL Block. // // A CAPL-DLL can be used by more than one CAPL-Block, so every piece of // information thats like a global variable in CAPL, must now be wrapped into // an instance of an object. // ============================================================================ void CAPLEXPORT far CAPLPASCAL appInit (uint32 handle) { CaplInstanceData* instance = GetCaplInstanceData(handle); if ( NULL==instance ) { VServiceMap::iterator lSearchService(gServiceMap.find(handle)); if ( gServiceMap.end()!=lSearchService ) { VIACapl* service = lSearchService->second; try { instance = new CaplInstanceData(service); } catch ( std::bad_alloc& ) { return; // proceed without change } instance->GetCallbackFunctions(); gCaplMap[handle] = instance; } } } void CAPLEXPORT far CAPLPASCAL appEnd (uint32 handle) { CaplInstanceData* inst = GetCaplInstanceData(handle); if (inst==NULL) { return; } inst->ReleaseCallbackFunctions(); delete inst; inst = NULL; gCaplMap.erase(handle); } long CAPLEXPORT far CAPLPASCAL appSetValue (uint32 handle, long x) { CaplInstanceData* inst = GetCaplInstanceData(handle); if (inst==NULL) { return -1; } return inst->ShowValue(x); } long CAPLEXPORT far CAPLPASCAL appReadData (uint32 handle, long a) { CaplInstanceData* inst = GetCaplInstanceData(handle); if (inst==NULL) { return -1; } int16 x = (a>=0) ? +1 : -1; uint32 y = abs(a); int16 z = (int16)(a & 0x0f000000) >> 24; inst->DllVersion("Version 1.1"); inst->DllInfo("DLL: processing"); uint8 databytes[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; inst->ArrayValues( 0xaabbccdd, sizeof(databytes), databytes, 0x01); return inst->ShowDates( x, y, z); } // ============================================================================ // VIARegisterCDLL // ============================================================================ VIACLIENT(void) VIARegisterCDLL (VIACapl* service) { uint32 handle; VIAResult result; if (service==NULL) { return; } result = service->GetCaplHandle(&handle); if(result!=kVIA_OK) { return; } // appInit (internal) resp. "DllInit" (CAPL code) has to follow gServiceMap[handle] = service; } void ClearAll() { // destroy objects created by this DLL // may result from forgotten DllEnd calls VCaplMap::iterator lIter=gCaplMap.begin(); const long cNumberOfEntries = gCaplMap.size(); long i = 0; while ( lIter!=gCaplMap.end() && i=1400 // >= Visual Studio 2005 _splitpath_s( path_buffer, drive, dir, fname, ext ); strcpy_s(gModuleName, fname); #else _splitpath( path_buffer, drive, dir, fname, ext ); strcpy(gModuleName, fname); #endif return 1; // Indicate that the DLL was initialized successfully. } case DLL_PROCESS_DETACH: { ClearAll(); return 1; // Indicate that the DLL was detached successfully. } } return 1; }