Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. ATL / WTL / STL
  4. Is forward declaration of ATL autogenerated _com_ptr_t possible?

Is forward declaration of ATL autogenerated _com_ptr_t possible?

Scheduled Pinned Locked Moved ATL / WTL / STL
c++helpcomquestion
8 Posts 2 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Stone Free
    wrote on last edited by
    #1

    In normal C++ when a class header only contains a reference or a pointer to a class it is better to not #include the definition but wait until the .cpp file to avoid coupling/avoid recompilation. In our of our class headers the reference concerned is to a smart pointer generated from a #import, in other words a smart pointer of the form _COM_SMARTPTR_TYPEDEF(IComInterface, &__uuidof(IComInterface)) Which expands to typedef _com_ptr_t<_com_IIID<icominterface,> > IComInterface; I think the problem is that the __declspec(uuid("GUID VALUE")) which is attached to the forward declaration of the IComInterface struct like __stdcall and __fastcall is part of the declaration and so will produce different types depending on the contents of uuid. The problem however is that the uuid contents will be autogenerated by the #import line, and so it won't be possible know ahead of time to know what to put in the typedef. I also think that the $(InputName)_i.c file generated when building the COM component won't help because although it contains the correct GUID it won't be in the correct form for __uuidof

    S 1 Reply Last reply
    0
    • S Stone Free

      In normal C++ when a class header only contains a reference or a pointer to a class it is better to not #include the definition but wait until the .cpp file to avoid coupling/avoid recompilation. In our of our class headers the reference concerned is to a smart pointer generated from a #import, in other words a smart pointer of the form _COM_SMARTPTR_TYPEDEF(IComInterface, &__uuidof(IComInterface)) Which expands to typedef _com_ptr_t<_com_IIID<icominterface,> > IComInterface; I think the problem is that the __declspec(uuid("GUID VALUE")) which is attached to the forward declaration of the IComInterface struct like __stdcall and __fastcall is part of the declaration and so will produce different types depending on the contents of uuid. The problem however is that the uuid contents will be autogenerated by the #import line, and so it won't be possible know ahead of time to know what to put in the typedef. I also think that the $(InputName)_i.c file generated when building the COM component won't help because although it contains the correct GUID it won't be in the correct form for __uuidof

      S Offline
      S Offline
      Stuart Dootson
      wrote on last edited by
      #2

      Try declaring a variable that (in some .cpp file) you'll define & initialise to the IID of the interface, like this:

      class ITest ;
      extern const IID ITest_IID;
      _COM_SMARTPTR_TYPEDEF(ITest, ITest_IID);

      That correctly forward declares ITestPtr so you can a) use a reference to it without needing the definition of ITest or ITest_IID, but b) can use the thing referred to once ITest and ITest_IID have been defined.

      Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

      S 1 Reply Last reply
      0
      • S Stuart Dootson

        Try declaring a variable that (in some .cpp file) you'll define & initialise to the IID of the interface, like this:

        class ITest ;
        extern const IID ITest_IID;
        _COM_SMARTPTR_TYPEDEF(ITest, ITest_IID);

        That correctly forward declares ITestPtr so you can a) use a reference to it without needing the definition of ITest or ITest_IID, but b) can use the thing referred to once ITest and ITest_IID have been defined.

        Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

        S Offline
        S Offline
        Stone Free
        wrote on last edited by
        #3

        I get the error "redefinition; different basic types" when the #import defines the real thing.

        S 1 Reply Last reply
        0
        • S Stone Free

          I get the error "redefinition; different basic types" when the #import defines the real thing.

          S Offline
          S Offline
          Stuart Dootson
          wrote on last edited by
          #4

          You need to decouple things a bit more in that case. Here's an example that builds: In the .h file:

          class ITest ;
          extern const IID ITest_IID;
          _COM_SMARTPTR_TYPEDEF(ITest, ITest_IID);

          In the .cpp file:

          #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

          class ITest : public Excel::_Application {};
          const IID ITest_IID = __uuidof(Excel::_Application);

          This defines a smart pointer, ITestPtr that wraps an Excel _Application pointer.

          Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

          S 1 Reply Last reply
          0
          • S Stuart Dootson

            You need to decouple things a bit more in that case. Here's an example that builds: In the .h file:

            class ITest ;
            extern const IID ITest_IID;
            _COM_SMARTPTR_TYPEDEF(ITest, ITest_IID);

            In the .cpp file:

            #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

            class ITest : public Excel::_Application {};
            const IID ITest_IID = __uuidof(Excel::_Application);

            This defines a smart pointer, ITestPtr that wraps an Excel _Application pointer.

            Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

            S Offline
            S Offline
            Stone Free
            wrote on last edited by
            #5

            It works up to a point, but the moment I introduce an accessor function to return a valid COM object the type ITest I get error C2027: use of undefined type 'ITest' So: HashImport.h

            #pragma once

            #include struct ITest;
            extern const IID ITest_IID;
            _COM_SMARTPTR_TYPEDEF(ITest, ITest_IID);

            class CHashImport
            {
            public:
            CHashImport();
            ~CHashImport();
            HRESULT GetImpl(ITestPtr &pImpl);
            };

            HashImport.cpp

            #include "StdAfx.h"
            #include "Hashimport.h"

            #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

            struct ITest : public Excel::_Application {};

            using namespace Excel;

            const IID ITest_IID = __uuidof(Excel::_Application);

            CHashImport::CHashImport()
            {
            ITestPtr ptr;
            GetImpl(ptr);
            }

            CHashImport::~CHashImport()
            {
            }

            HRESULT CHashImport::GetImpl(ITestPtr &pImpl)
            {
            pImpl = ITestPtr(__uuidof(Excel::Application));
            _bstr_t appname = pImpl->GetValue();
            return S_OK;
            }

            referenceheader.h

            #pragma once
            #include "hashimport.h"

            class CReferenceHeader
            {
            public:
            CReferenceHeader();
            ~CReferenceHeader();
            };

            referenceheader.cpp

            #include "StdAfx.h"
            #include "Referenceheader.h"

            CReferenceHeader::CReferenceHeader()
            {
            }

            CReferenceHeader::~CReferenceHeader()
            {
            }

            main.cpp

            #include "stdafx.h"
            #include "hashimport.h"
            #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

            int _tmain(int argc, _TCHAR* argv[])
            {
            ::CoInitialize(NULL);
            CHashImport import;
            //ITestPtr pTest; //error C2027: use of undefined type 'ITest'
            //import.GetImpl(pTest);
            //c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\comip.h(822) : error C2227: left of '->Release' must point to class/struct/union

            ::CoUninitialize();
            return 0;
            

            }

            S 1 Reply Last reply
            0
            • S Stone Free

              It works up to a point, but the moment I introduce an accessor function to return a valid COM object the type ITest I get error C2027: use of undefined type 'ITest' So: HashImport.h

              #pragma once

              #include struct ITest;
              extern const IID ITest_IID;
              _COM_SMARTPTR_TYPEDEF(ITest, ITest_IID);

              class CHashImport
              {
              public:
              CHashImport();
              ~CHashImport();
              HRESULT GetImpl(ITestPtr &pImpl);
              };

              HashImport.cpp

              #include "StdAfx.h"
              #include "Hashimport.h"

              #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

              struct ITest : public Excel::_Application {};

              using namespace Excel;

              const IID ITest_IID = __uuidof(Excel::_Application);

              CHashImport::CHashImport()
              {
              ITestPtr ptr;
              GetImpl(ptr);
              }

              CHashImport::~CHashImport()
              {
              }

              HRESULT CHashImport::GetImpl(ITestPtr &pImpl)
              {
              pImpl = ITestPtr(__uuidof(Excel::Application));
              _bstr_t appname = pImpl->GetValue();
              return S_OK;
              }

              referenceheader.h

              #pragma once
              #include "hashimport.h"

              class CReferenceHeader
              {
              public:
              CReferenceHeader();
              ~CReferenceHeader();
              };

              referenceheader.cpp

              #include "StdAfx.h"
              #include "Referenceheader.h"

              CReferenceHeader::CReferenceHeader()
              {
              }

              CReferenceHeader::~CReferenceHeader()
              {
              }

              main.cpp

              #include "stdafx.h"
              #include "hashimport.h"
              #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

              int _tmain(int argc, _TCHAR* argv[])
              {
              ::CoInitialize(NULL);
              CHashImport import;
              //ITestPtr pTest; //error C2027: use of undefined type 'ITest'
              //import.GetImpl(pTest);
              //c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\comip.h(822) : error C2227: left of '->Release' must point to class/struct/union

              ::CoUninitialize();
              return 0;
              

              }

              S Offline
              S Offline
              Stuart Dootson
              wrote on last edited by
              #6

              Yeah, that's because main.cpp needs a full definition of ITest or whatever the smart pointer class would be. You have no option at that point but to have a full definition of ITest. Rename HashImport.h to HashImportFwd.h (like you have ios and iosfwd in the standard library). Then create a new header called HashImport.h containing this:

              #include "HashimportFwd.h"

              #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

              struct ITest : public Excel::_Application {};

              Now, use HashImportFwd.h where the forward declaration is all that's needed and HashImport.h where you need the full definition.

              Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

              S 1 Reply Last reply
              0
              • S Stuart Dootson

                Yeah, that's because main.cpp needs a full definition of ITest or whatever the smart pointer class would be. You have no option at that point but to have a full definition of ITest. Rename HashImport.h to HashImportFwd.h (like you have ios and iosfwd in the standard library). Then create a new header called HashImport.h containing this:

                #include "HashimportFwd.h"

                #import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")

                struct ITest : public Excel::_Application {};

                Now, use HashImportFwd.h where the forward declaration is all that's needed and HashImport.h where you need the full definition.

                Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                S Offline
                S Offline
                Stone Free
                wrote on last edited by
                #7

                Thanks for all your help Stuart :-D It's working fine! I'm trying to come up with some macros to make it configurable, but the inability to redefine a #define as part of another #define doesn't seem to be possible.

                S 1 Reply Last reply
                0
                • S Stone Free

                  Thanks for all your help Stuart :-D It's working fine! I'm trying to come up with some macros to make it configurable, but the inability to redefine a #define as part of another #define doesn't seem to be possible.

                  S Offline
                  S Offline
                  Stuart Dootson
                  wrote on last edited by
                  #8

                  Stone Free wrote:

                  I'm trying to come up with some macros to make it configurable, but the inability to redefine a #define as part of another #define doesn't seem to be possible.

                  No, it's not - the pre-processor's not that clever (probably just as well, really)

                  Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups