⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sample.cpp

📁 一个OPC服务器开发的源代码。结构清晰
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      static const unsigned char legalq[] = {
    OPC_QUALITY_CONFIG_ERROR    ,    OPC_QUALITY_NOT_CONNECTED   ,
    OPC_QUALITY_DEVICE_FAILURE  ,    OPC_QUALITY_SENSOR_FAILURE  ,
    OPC_QUALITY_LAST_KNOWN      ,    OPC_QUALITY_COMM_FAILURE    ,
    OPC_QUALITY_OUT_OF_SERVICE  ,

// STATUS_MASK Values for Quality = UNCERTAIN
    OPC_QUALITY_LAST_USABLE     ,    OPC_QUALITY_SENSOR_CAL      ,
    OPC_QUALITY_EGU_EXCEEDED    ,    OPC_QUALITY_SUB_NORMAL      ,

// STATUS_MASK Values for Quality = GOOD
    OPC_QUALITY_LOCAL_OVERRIDE  };

      tv[TI_quality].tvState.tsTime = ft;
      tv[TI_quality].tvState.tsQuality = 
        legalq[((unsigned)ft.dwLowDateTime >> 24) % SIZEOF_ARRAY(legalq)];

/** OPTIONAL: change the STRING variable: */
      WCHAR wstr[32];
      local_text(wstr, (ft.dwLowDateTime >> 24) % 7, 0);
      VariantClear(&tv[TI_string].tvValue); /* don't miss it! 
                                    BSTR is not a simple type */
      V_BSTR(&tv[TI_string].tvValue) = SysAllocString(wstr);
      V_VT(&tv[TI_string].tvValue) = VT_BSTR;
      tv[TI_string].tvState.tsTime = ft;

/** OPTIONAL: change the ARRAY variable: */
      if (ti[TI_array]) /* has been successfuly initialized? */
        {
          long ix0 = 1, val = (long)zuzu;
          SafeArrayPutElement(V_ARRAY(&tv[TI_array].tvValue), &ix0, &val);
          tv[TI_array].tvTi = ti[TI_array];
          tv[TI_array].tvState.tsTime = ft;
        }

/** MANDATORY: send all the values into the cache: */
      loCacheUpdate(my_service, TI_MAX, tv + 1, 0);

      LeaveCriticalSection(&lk_values);

      if (pause) 
        {
/* IMPORTANT: force unloading of an out-of-proc 
   if not connected during PAUSE millisec */
          unsigned tnow = GetTickCount();
          if (tnow - starttime >= pause)
            {
              pause = 0;
              my_CF.serverRemove();
            }
        }

      if (test_mode)
        {
/* OPTIONAL: simulate client's connections to test loSetState
      and track down resource leakage */
          static int xx;
          static IUnknown *cli;
          unsigned tnow = GetTickCount();
          if (tnow - starttime >= 2500)
            {
              starttime = tnow;
/* To test for unreleased handles / threads
   run taskmgr and see what's happen...*/
              if (cli) 
                {
                  cli->Release(); cli = 0;
                  if (5 < ++xx) 
                    {
                      puts("SHUTDOWN initiated...");
                      loSetState(my_service, 0, loOP_SHUTDOWN,
                                 OPC_STATUS_SUSPENDED, "forced shutdown");
                      my_CF.serverRemove();
                      test_mode = 2;
                    }
                }
              else if (test_mode == 1)
                {
                  my_CF.CreateInstance(0, IID_IUnknown, (void **)&cli);
                }
              else
                {
                  puts("DISCONNECT initiated...");
                  loSetState(my_service, 0, loOP_STOP | loOP_DISCONNECT,
                             OPC_STATUS_SUSPENDED, "forced shutdown");
                }
            }
        } /* end of if (test_mode... */
    } /* end of loop */

  if (0 == my_CF.is_out_of_proc) /* For in-proc servers only! */
    {
      EnterCriticalSection(&my_CF.lk_count);
      driver_destroy();
      LeaveCriticalSection(&my_CF.lk_count);
    }
  
  UL_MESSAGE((LOGID, "All clean. exiting..."));
}


/***************************************************************************
 EXE-specefic stuff
 ***************************************************************************/

const char eClsidName[] = "LightOPC Sample server (exe)";
const char eProgID[] = "OPC.LightOPC-exe";

HMODULE server_module = 0;
static int mymine(HINSTANCE hInstance, int argc, char *argv[]);

extern "C"
  int APIENTRY WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  static char *argv[3] = { "fake.exe", NULL, NULL };
  argv[1] = lpCmdLine;
  return mymine(hInstance, 2, argv);
}

extern "C" int main(int argc, char *argv[])
{
  return mymine(GetModuleHandle(NULL), argc, argv);
}

int mymine(HINSTANCE hInstance, int argc, char *argv[])
{
  int main_rc = 0;
  DWORD objid;
  int daemon = 0, pause = 20;
  const char *exit_msg = "Exiting...";
  server_module = hInstance;

  log = unilog_Create("LOPC-exe", "|LOPC-exe", "%!T", -1,       /* Max filesize: -1 unlimited, -2 -don't change */
                      ll_MESSAGE);        /* level [ll_FATAL...ll_DEBUG] */
  unilog_Redirect("LOPC-exe", "LightOPC", 0);
  unilog_Delete(log);
  log = unilog_Create("Lopc-Sample-exe", "|Lopc-Sample-exe", "", -1,    /* Max filesize: -1 unlimited, -2 -don't change */
                      ll_TRACE);        /* level [ll_FATAL...ll_DEBUG] */
  UL_DEBUG((LOGID, "WinMain(%s) invoked...", argv[0]));

  if (argv[1])
    {
      printf("%s\nClass %s :  ", argv[0], eProgID);
      if (strstr(argv[1], "/r"))
        {
          char np[FILENAME_MAX + 32];
          printf("Registering");
          GetModuleFileName(NULL, np + 1, sizeof(np) - 8);
          np[0] = '"'; strcat(np, "\"");
          
          if (strstr(argv[1], "/r")[2] == 'c') strcat(np, " /c");

          if (loServerRegister(&CLSID_LightOPCServerEXE, 
                               eProgID, eClsidName, np, 0))
            {
              UL_ERROR((LOGID, "%!L Reg <%s> <%s> Failed", eProgID, argv[0]));
              puts(" FAILED");
              main_rc = 1;
            }
          else
            {
              UL_INFO((LOGID, "Reg <%s> <%s> Ok", eProgID, argv[0]));
              puts(" Succeeded");
            }
          goto Finish;
        }
      else if (strstr(argv[1], "/u"))
        {
          printf("UnRegistering");
          if (loServerUnregister(&CLSID_LightOPCServerEXE, eProgID))
            {
              UL_WARNING((LOGID, "%!L UnReg <%s> <%s> Failed", eProgID, argv[0]));
              puts(" FAILED");
              main_rc = 1;
            }
          else
            {
              UL_DEBUG((LOGID, "UnReg <%s> <%s> Ok", eProgID, argv[0]));
              puts(" Success");
            }
          goto Finish;
        }
      else if (strstr(argv[1], "/c") || strstr(argv[1], "/C"))
        {
          UL_MESSAGE((LOGID, "Creating new console..."));
          use_console = 1;
          AllocConsole();
          goto Cont;
        }
      else if (strstr(argv[1], "/daemon"))
        {
          UL_MESSAGE((LOGID, "Running as DAEMON"));
          puts("Running as DAEMON...");
          daemon = 1; use_console = 1;
          goto Cont;
        }
      else if (strstr(argv[1], "/detach"))
        {
          UL_MESSAGE((LOGID, "Running as Detached DAEMON"));
          puts("Running as Detached DAEMON...");
          daemon = 2;
          goto Cont;
        }
      else if (strstr(argv[1], "/test"))
        {
          UL_MESSAGE((LOGID, "Running in TEST mode"));
          puts("Running in TEST mode...");
          daemon = 1; use_console = 1; test_mode = 1;
          goto Cont;
        }
      else
        {
          UL_WARNING((LOGID, "unknown option <%s>", argv[1]));
          printf("Unknown option <%s>", argv[1]);
          puts("\nOne of following flags can be specified:"
               "\n\t/r       - register;"
               "\n\t/u       - unregister;"
               "\n\t/rc      - register to start with /c key;"
               "\n\t/c       - create console window;"
               "\n\t/daemon  - run in daemon mode;"
               "\n\t/test    - run in test mode for 25 seconds;"
               "\n\t/detach  - run in unbreakable daemon mode.");
          goto Cont;
        }
      goto Finish;
    }

Cont: /* Attempt to start the server */
  if (1 != daemon && 0 == use_console)
    FreeConsole();

  my_CF.is_out_of_proc = my_CF.server_inuse = 1;

  if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
    {
      exit_msg = "CoInitializeEx() failed. Exiting...";
      UL_ERROR((LOGID, exit_msg));
      goto Finish;
    }

  pause = 20; /* 20 sec can be too short for remote connections */
  if (use_console && !daemon)
    printf("Waiting %d seconds for connection...\n", pause);

  if (driver_init(0))
    {
      exit_msg = "driver_init() failed. Exiting...";
      UL_ERROR((LOGID, exit_msg));
    }
  else if (FAILED(CoRegisterClassObject(CLSID_LightOPCServerEXE, &my_CF,
                                        CLSCTX_LOCAL_SERVER |
                                        CLSCTX_REMOTE_SERVER |
                                        CLSCTX_INPROC_SERVER,
                                        REGCLS_MULTIPLEUSE, &objid)))
    {
      exit_msg = "CoRegisterClassObject() failed. Exiting...";
      UL_ERROR((LOGID, exit_msg));
    }
  else
    {
      if (daemon) pause = 0;          // infinite

      my_CF.serverAdd(); /* Oops. This will prewent our server from unloading
                till PAUSE elapsed and simulate() do my_CF.serverRemove() */
/* STARTing the simulator */
      simulate(pause * 1000); /* sec -> millisec; */ 
/* FINISHED */
      if (FAILED(CoRevokeClassObject(objid)))
        UL_WARNING((LOGID, "CoRevokeClassObject() failed..."));
    }
  driver_destroy();
  CoUninitialize();

Finish:
  if (use_console) puts(exit_msg);

  UL_DEBUG((LOGID, "WinMain(%s) finished", argv[0]));
  unilog_Delete(log);
  log = 0;
  return main_rc;
}

/***************************************************************************
 DLL-specefic stuff
 ***************************************************************************/

static void dll_simulator_wait(void) /* in-proc specefic */
{
  for(;;) 
    {
      int finished;
      EnterCriticalSection(&my_CF.lk_count); 
      finished = my_service == 0 || my_CF.server_inuse;
      LeaveCriticalSection(&my_CF.lk_count);
      if (finished) break;
      else Sleep(500);
    }
  /* Looking for conditional variables?
     See unilog/condsb.[hc] */
}

static void dll_simulator_start(void) /* in-proc specefic */
{
  int rv;
  EnterCriticalSection(&my_CF.lk_count);
  if (!my_service)
    {
      if (rv = driver_init( /* inproc only options! */
#if 1
               loDf_FREEMARSH | loDf_BOTHMODEL
#else
               0
#endif
        ))
        {
           UL_ERROR((LOGID, "!%e driver_init FAILED:", rv));
        }
      else if (-1 == (int)_beginthread((void(*)(void *))simulate, 0, (void *)0))
        {
           UL_ERROR((LOGID, "!%E _beginthread() FAILED:"));
           driver_destroy();
        }
      else my_CF.server_inuse = 1;
    }

  LeaveCriticalSection(&my_CF.lk_count);  
}

extern "C"
  BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
  if (fdwReason == DLL_PROCESS_ATTACH)
    {
      server_module = hinstDLL;

      log = unilog_Create("LOPC-dll", "|LOPC-dll", "%!T", -1,   /* Max filesize: -1 unlimited, -2 -don't change */
                          ll_DEBUG);    /* level [ll_FATAL...ll_DEBUG] */
      unilog_Redirect("LOPC-dll", "LightOPC", 0);
      unilog_Delete(log);
      log = unilog_Create("Lopc-Sample-dll", "|Lopc-Sample-dll", "", -1,        /* Max filesize: -1 unlimited, -2 -don't change */
                          ll_DEBUG);    /* level [ll_FATAL...ll_DEBUG] */
      UL_DEBUG((LOGID, "DllMAin(process_attach)"));
      //driver_init();    /* not the best place */
    }
  else if (fdwReason == DLL_PROCESS_DETACH)
    {

      UL_DEBUG((LOGID, "DllMAin(process_detach)"));
      unilog_Delete(log);
      log = 0;
      //driver_destroy(); /* not the best place */
    }

  return TRUE;
}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
  UL_DEBUG((LOGID, "DllGetClassObject() ..."));

  if (rclsid == CLSID_LightOPCServerDLL || rclsid == CLSID_LightOPCServerEXE)
    {
      HRESULT hr = my_CF.QueryInterface(riid, ppv);
      UL_DEBUG((LOGID, "%!l DllGetClassObject() >>%04X %s", hr, hr,
                FAILED(hr) ? "failed" : "Ok"));
      return hr;
    }
  UL_DEBUG((LOGID, "DllGetClassObject() >>CLASS_E_CLASSNOTAVAILABLE"));
  return CLASS_E_CLASSNOTAVAILABLE;
}

STDAPI DllCanUnloadNow(void)
{
  UL_DEBUG((LOGID, "DllCanUnloadNow() invoked servers=%d", my_CF.server_count));
  my_CF.serverAdd();
  my_CF.serverRemove(); /* Force stopping the simulator if not used */
/* the simulator can be restarted in ICF::CreateInstance() if requested */
  if (0 == my_CF.server_inuse) 
    {
      dll_simulator_wait();
      if (0 == my_CF.server_inuse) return S_OK;
    }
  return S_FALSE;
}

/* standard OLE registration stuff */

const char dClsidName[] = "LightOPC Sample server (dll)";
const char dProgID[] = "OPC.LightOPC-dll";

STDAPI DllRegisterServer(void)
{
  char sFile[FILENAME_MAX + 16];
  GetModuleFileName(server_module, sFile, sizeof(sFile) - 1);
  UL_DEBUG((LOGID, "DllRegister(%s)", sFile));
  return loServerRegister(&CLSID_LightOPCServerDLL, dProgID, dClsidName, sFile,
          "Both") ? SELFREG_E_CLASS: S_OK;
}

STDAPI DllUnregisterServer(void)
{
  return loServerUnregister(&CLSID_LightOPCServerDLL, dProgID)? SELFREG_E_CLASS: S_OK;
}

/* OPTIONAL: **************** special helpers ******************************/

static void local_text(WCHAR buf[32], unsigned nn, LCID lcid)
{
  char sbt[40];
  long lcp = CP_ACP;
  unsigned nx;

  nn %= 7;
  /* Nasty Win95 doesn't have proper unicode support.
     So we getting singlebyte strings and then converting them to unicode.
     But we've to know the right codepage first! 
     CP_ACP is our cp. An OPC client may choose other. */

  if (0 == GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, sbt, sizeof(sbt)-1))
    goto Failure;
  lcp = strtoul(sbt, 0, 10);

  /* How does called "Monday"+nn in LCID country? */
  if (0 == GetLocaleInfoA(lcid, LOCALE_SDAYNAME1 + nn, sbt, sizeof(sbt) - 1))
    goto Failure;

  nx = strlen(sbt);
  if (sizeof(sbt) - nx > 12)
    {
      sbt[nx++] = ' '; /* Append language name [OPTIONAL] */
      if (0 == GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, sbt + nx,
                         sizeof(sbt) - nx - 1) && 
          0 == GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, sbt + nx,
                         sizeof(sbt) - nx - 1) )
        sbt[--nx] = 0; /* ... or the country name */
    }
  if (0 == MultiByteToWideChar(lcp, 0, sbt, -1, buf, 32))
    {
    Failure:
      swprintf(buf, L"%d [string]", nn);
    }
// UL_DEBUG((LOGID, "locals lcid:%x cp:%d [%s] [%ls]%d", 
   //lcid, lcp, sbt, buf, wcslen(buf)));
}

/******************* This is the end... ************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -