Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6754065
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T13:14:10+00:00 2026-05-26T13:14:10+00:00

I am currently working on a project that has a number of COM objects

  • 0

I am currently working on a project that has a number of COM objects written in C++ with ATL.

Currently, they are all defined in .cpp and .idl files that are directly compiled into the COM DLL.

To allow unit tests to be written easier, I am planning on moving the implementation of the COM objects out into a separate static library. That library can then be linked in to the main DLL, and the separate unit test project.

I am assuming that there’s nothing particularly special about the code generated by ATL, and that this will work much like all other C++ code when it comes to linking with static libraries. However, I don’t have too much actual knowledge of ATL myself so don’t know if this is really the case.

Will this work as I’m expecting? Or are there pitfalls that I should look out for?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T13:14:11+00:00Added an answer on May 26, 2026 at 1:14 pm

    There are gotchas since LIBs are pulled in only if they are referenced, as opposed to OBJs which are explicitly included.

    Larry Osterman discussed some of the subtleties a few years ago:

    When I moved my code into a library, what happened to my ATL COM
    objects?

    A caveat: This post discusses details of how ATL7 works. For other
    version of ATL, YMMV. The general principals apply for all
    versions, but the details are likely to be different.

    My group’s recently been working on reducing the number of DLLs
    that make up the feature we’re working on (going from somewhere
    around 8 to 4). As a part of this, I’ve spent the past couple of
    weeks consolidating a bunch of ATL COM DLL’s.

    To do this, I first changed the DLLs to build libraries, and then
    linked the libraries together with a dummy DllInit routine (which
    basically just called CComDllModule::DllInit()) to make the DLL.

    So far so good. Everything linked, and I got ready to test the new
    DLL.

    For some reason, when I attempted to register the DLL, the
    registration didn’t actually register the COM objects. At that
    point, I started kicking my self for forgetting one of the
    fundamental differences between linking objects together to make an
    executable and linking libraries together to make an executable.

    To explain, I’ve got to go into a bit of how the linker works. When
    you link an executable (of any kind), the linker loads all the
    sections in the object files that make up the executable. For each
    extdef symbol in the object files, it starts looking for a public
    symbol that matches the symbol.

    Once all of the symbols are matched, the linker then makes a second
    pass combining all the .code sections that have identical contents
    (this has the effect of collapsing template methods that expand into
    the same code (this happens a lot with CComPtr)).

    Then a third pass is run. The third pass discards all of the
    sections that have not yet been referenced. Since the sections
    aren’t referenced, they’re not going to be used in the resulting
    executable, so to include them would just bloat the executable.

    Ok, so why didn’t my ATL based COM objects get registered? Well,
    it’s time to play detective.

    Well, it turns out that you’ve got to dig a bit into the ATL code to
    figure it out.

    The ATL COM registration logic gets picked in the CComModule
    object. Within that object, there’s a method
    RegisterClassObjects, which redirects to
    AtlComModuleRegisterClassObjects. This function walks a list of
    _ATL_OBJMAP_ENTRY structures and calls the RegisterClassObject
    on each structure. The list is retrieved from the
    m_ppAutoObjMapFirst member of the CComModule (ok, it’s really a
    member of the _ATL_COM_MODULE70, which is a base class for the
    CComModule). So where did that field come from?

    It’s initialized in the constructor of the CAtlComModule, which
    gets it from the __pobjMapEntryFirst global variable. So where’s
    __pobjMapEntryFirst field come from?

    Well, there are actually two fields of relevance,
    __pobjMapEntryFirst and __pobjMapEntryLast.

    Here’s the definition for the __pobjMapEntryFirst:

     __declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL;
    

    And here’s the definition for __pobjMapEntryLast:

     __declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL;
    

    Let’s break this one down:

    • __declspec(selectany): __declspec(selectany) is a directive to
      the linker to pick any of the similarly named items from the section
      – in other words, if a __declspec(selectany) item is found
      in multiple object files, just pick one, don’t complain about it
      being multiply defined.

    • __declspec(allocate("ATL$__a")): This one’s the one that makes
      the magic work. This is a declaration to the compiler, it tells the
      compiler to put the variable in a section named "ATL$__a" (or
      "ATL$__z").

    Ok, that’s nice, but how does it work?

    Well, to get my ATL based COM object declared, I included the
    following line in my header file:

     OBJECT_ENTRY_AUTO(<my classid>, <my class>)
    

    OBJECT_ENTRY_AUTO expands into:

    #define OBJECT_ENTRY_AUTO(clsid, class) \
    
            __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }; \
    
            extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \
    
            OBJECT_ENTRY_PRAGMA(class)
    

    Notice the declaration of __pobjMap_##class above – there’s
    that declspec(allocate("ATL$__m")) thingy again. And that’s where
    the magic lies. When the linker’s laying out the code, it sorts
    these sections alphabetically – so variables in the ATL$__a
    section will occur before the variables in the ATL$__z section.
    So what’s happening under the covers is that ATL’s asking the linker
    to place all the __pobjMap_<class name> variables in the
    executable between __pobjMapEntryFirst and __pobjMapEntryLast.

    And that’s the crux of the problem. Remember my comment above about
    how the linker works resolving symbols? It first loads all the items
    (code and data) from the OBJ files passed in, and resolves all the
    external definitions for them. But none of the files in the wrapper
    directory (which are the ones that are explicitly linked) reference
    any of the code in the DLL (remember, the wrapper doesn’t do much more
    than simply calling into ATL’s wrapper functions – it doesn’t
    reference any of the code in the other files.

    So how did I fix the problem? Simple. I knew that as soon as the
    linker pulled in the module that contained my COM class definition,
    it’d start resolving all the items in that module. Including the
    __objMap_<class>, which would then be added in the right location so that ATL would be able to pick it up. I put a dummy function call
    called ForceLoad<MyClass> inside the module in the library, and
    then added a function called CallForceLoad<MyClass> to my DLL
    entry point file (note: I just added the function – I didn’t
    call it from any code).

    And voila, the code was loaded, and the class factories for my COM
    objects were now auto-registered.

    What was even cooler about this was that since no live code called
    the two dummy functions that were used to pull in the library, pass
    three of the linker discarded the code!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm currently working on a project that has scope to become quite large, however
I'm currently working on a project that has a svn repository. I'm used to
I'm currently working on a project that has a sizable amount of both client
I'm working on a project that currently has zero users but we would like
I am currently working on a vba project that has the end user copy/paste
I am currently working on a project which contains a window, that has a
I'm currently working on a project that has a very interesting set of requirements.
I am currently working on a project that is moving from .NET 2.0 to
I am currently working on a project that will store specific financial information about
I'm currently working on a project that hooks into various system calls and writes

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.