2 Replies Latest reply on Jul 13, 2012 1:16 PM by spilon

    Porting OPC HDA client from 32-bit to 64-bit


      I am developing an OPCHDA client written in C language to access PI-OPCHDA server (2010 R2). This client was working fine if it was compiled under window 32-bit environment. Since the requirement is to let this client to run under window 64-bit environment, I encountered several problems which were not occurred under win 32-bit environment. Does anybody have experience to solve the problem I encounter:

      1. CoTaskMemfree after GetEnum( method. I have a crash to complain the invalid address on ppIEnumString which I knew it has not being free yet. The doc said this parameter was [out] **ppIEnumString I defined LPENUMSTRING *ppIEnumString; and pass &ppIEnumString in GetEnum method. Anybody experienced this problem before ? How do I treat ? This problem was not happened under win 32 environment
      2. CoTaskmemFree after the query is finished At the end of query, I was using CoTaskMemFree if (iOPCHDA_Browser != NULL) { CoTaskMemFree(iOPCHDA_Browser); } I got a crash also debugger complained iOPCHDA_Browser was in invalid address which was not occurred under win 32 environment and I believe the iOPCHDA_Browser has not been free yet
      3. Crashed on ReadAttribute method under SyncRead // Page 61: HDA Spec Version 1.20 // Find the meta data value (meta data must be legal attribute (IE has mapping) to OPCHDA attributes hr = (*iOPCHDA_SyncRead->lpVtbl->ReadAttribute )( // HRESULT ( STDMETHODCALLTYPE *ReadRaw )( // IOPCHDA_SyncRead * This, iOPCHDA_SyncRead, // [out][in] OPCHDA_TIME *htStartTime, htStartTime, // [out][in] OPCHDA_TIME *htEndTime, htEndTime, // The structure of the current serverHandle opcHandle, mappingCount, pdwAttributeIDs, &ppAttributeValues, &ppErrors);

        I got crash on invalid address and this problem was not occurred under win 32. Since PI-OPCHDA client tool was 32 bit and has a very limited GUI and PI-OPCHDA server is also 32-bit, has anybody successfully porting their OPCHDA client running under win 64-bit environment?
        • Re: Porting OPC HDA client from 32-bit to 64-bit

          Your problem should not be related to calling a 32-bit COM Server component with either a 32 or 64-bit COM client. As a reference, I have added information regarding configuration options for a COM/DCOM objects stored in the registry.


          If the preferredServerBitness value is not present, then:

          • If the computer that hosts the server is running Windows XP or Windows Server 2003 without SP1 or later installed, then COM will prefer a 64-bit version of the server if available; otherwise it will activate a 32-bit version of the server.
          • If the computer that hosts the server is running Windows Server 2003 with SP1 or later installed, then COM will try to match the server architecture to the client architecture. In other words, for a 32-bit client, COM will activate a 32-bit server if available; otherwise it will activate a 64-bit version of the server. For a 64-bit client, COM will activate a 64-bit server if available; otherwise it will activate a 32-bit server.

          The client can also specify its own architecture preference via the CLSCTX_ACTIVATE_32_BIT_SERVER and CLSCTX_ACTIVATE_64_BIT_SERVER flags, and these will override the server's preference. For more information, and a chart of possible interactions between client and server architecture preferences, see CLSCTX.


          The PI OPC DA/HDA Server does not set this flag/parameter. This should not have to do with 32 vs 64 bit COM Server.


          Make sure you use UINT_PTR or INT_PTR type to manipulate your pointers with the CoTaskMemFree function and not the int, long, ULONG or DWORD ones. You would end up with wrong size of pointers and this will throw errors on a 64-bit Windows.


          If you get a pointer to OPCHDA_BROWSER interface named pphBrowser when you invoke IOPCHDA_Server::CreateBrowse method, why are you not calling the COM Release method as shown below?

          if (*pphBrowser)
               *pphBrowser = NULL;

          Another option could be to make use of smart pointers that would unreference themselves in case of problem.


          As you described you have utilized different environments: 32-bit and 64-bit ones, this may imply you have worked on different OSes such as Windows XP, Windows 7 or Windows Server 2008. Memory management rules are not the same on all of these systems. On Windows XP memory management, particularly the heap, is not handled as strictly as it is now with Windows 7 or Windows Server 2008. This may explain why it worked on one and not the other.


          Can you try to release your object by default Release method and see if it fixes your problem?

            • Re: Porting OPC HDA client from 32-bit to 64-bit

              @Yao Chen: have you ever considered other approaches than OPC? There might be better alternatives to reading data out of PI in a more robust and more performant way - for instance, using the PI SDK.


              I don't know what your requirements are and what drove you to choose the OPC HDA route, but essentially the OPC HDA specification is not something that is actively maintained and enhanced anymore (and hasn't been for years: the latest version of the spec, 1.20, is dated December 2003). Now I let you guess how much work went into (or will go into) our PI OPC DA/HDA Server... ;)


              Instead, you might want to consider writing your client using our PI SDK, a much richer, more intuitive and more performant way to access the PI System. It won't give you access to the PI Asset Framework (AF) like the AF SDK (a .NET API) does, but chances are you don't need it anyways, since you opted for OPC HDA.


              Please do not hesitate to post in the PI SDK Development forum if you need further assistance on this matter.