Event-driven detection of changes to the symbol table

ADS devices that support symbol names (PLC, NC, ...) store those names in an internal table. A handle is assigned here to each symbol. The symbol handle is necessary in order to be able to access the variables (see also Sample 9). If the symbol table changes because, for instance, a new PLC program is written into the controller, the handles must be ascertained once again. The following sample illustrates how changes to the symbol table can be detected.

Download: sample12-c-ads-dll-detectsymbolchanges.zip

#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <winbase.h>

// ADS headers
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsApi.h"


void __stdcall SymbolChanged(AmsAddr*, AdsNotificationHeader*, unsigned long);

void main()

  long           nErr;
  AmsAddr        Addr; 
  PAmsAddr           pAddr = &Addr; 
  ULONG          hNotification; 
  AdsNotificationAttrib  adsNotificationAttrib;

  // Open communication port on the ADS router
  AdsPortOpen();
  nErr = AdsGetLocalAddress(pAddr);
  if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
  
  // Select Port: TwinCAT2 PLC1
  pAddr->port = 801;

  // Specify attributes of the notification
  adsNotificationAttrib.cbLength = 1;
  adsNotificationAttrib.nTransMode = ADSTRANS_SERVERONCHA;
  adsNotificationAttrib.nMaxDelay = 5000000; // 500ms 
  adsNotificationAttrib.nCycleTime = 5000000; // 500ms

  // Start notification for changes to the symbol table
  nErr = AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_SYM_VERSION, 0, &adsNotificationAttrib, SymbolChanged, NULL, &hNotification);
  if (nErr) cerr << "Error: AdsSyncAddDeviceNotificationReq: " << nErr << '\n';

  // Wait for a key-press from the user
  _getch();

  // Stop notification
  nErr = AdsSyncDelDeviceNotificationReq(pAddr, hNotification);
  if (nErr) cerr << "Error: AdsSyncDelDeviceNotificationReq: " << nErr << '\n';

  // Close communication port
  nErr = AdsPortClose();
  if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n';
}

// Callback function
void __stdcall SymbolChanged(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)
{
  cout << "Symboltabelle hat sich geändert!\n";
  cout.flush();
}