0

Sorry if this is a basic question. Basically, I'm implementing a class with a bunch of static (and unchanging) resources that will be shared by all instances. The static resources need to be initialized once by being passed as out parameters to various functions. I wasn't sure exactly how to do this elegantly. At the moment, what I do is put all the necessary function calls within a lambda, or a private member function, and then I call that function in a static manner within the constructor, like so:

HRESULT MyClass::FinalConstruct()
{
    static HRESULT hr = []() {

        HRESULT hr;

        // Call necessary initializing functions,
        // passing static variables as out-parameters. For example:
        // (s_pUIA and s_pUIATreeWalker are static smart pointers that
        // need to be initialized)

        hr = CoCreateInstance(  __uuidof(CUIAutomation),
                                NULL,
                                CLSCTX_INPROC_SERVER,
                                IID_PPV_ARGS(&s_pUIA)  );
        if (FAILED(hr))
        {
            ATLTRACE("\nFailed to instantiate IUIAutomation object.\n");
            return hr;
        }

        hr = s_pUIA->get_ControlViewWalker(&s_pUIATreeWalker);
        if (FAILED(hr))
        {
            ATLTRACE("\nFailed to get IUIAutomation tree walker.\n");
            return hr;
        }

        // ...

        return hr;

    }();

    return hr;
}

I wasn't sure if there was a more acceptable way of doing this. Thank you very much for any input.

  • 1
    You *may* be interested in [std::call_once](https://en.cppreference.com/w/cpp/thread/call_once). – Jesper Juhl May 08 '20 at 15:37
  • use [`InitOnceExecuteOnce`](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initonceexecuteonce), however by fact c++ internal use this for initialize static *hr*. so you also write correct solution – RbMm May 08 '20 at 15:42
  • 1
    It wasn't clear to me what your situation was when I first read this question. Would it be fair to replace your comment with something like `foo(hr); // Initialize hr`? That would explain why you need something more complicated than a static member variable. – JaMiT May 08 '20 at 15:57
  • I'll add an example to illustrate the type of initialization I need to perform. –  May 08 '20 at 15:59
  • @loop123123 Please keep it simple. For example, at the moment the `winapi` tag looks unneeded, and it should probably stay that way (and be removed, but I'll hold off until I see the clarification). – JaMiT May 08 '20 at 16:02
  • Make sure to understand the implications of having COM interface pointers with static storage duration. Uninitializing COM has suddenly turned into a tough problem. – IInspectable May 08 '20 at 18:49
  • @IInspectable Well this is in the context of a shell extension, so I don't initialize or uninitialize COM anywhere myself. Is it still a problem to have static COM pointers in that situation? –  May 08 '20 at 18:59
  • I suppose that forces you to unconditionally return `S_FALSE` from [DllCanUnloadNow](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-dllcanunloadnow) since the reference count won't ever drop to zero for interfaces with static storage duration. – IInspectable May 08 '20 at 20:46
  • @IInspectable Hm, well I just went into debug mode, with the debugger attached to Explorer. I opened and used my shell extension, then closed the Explorer window and waited. And sure enough, after a while the output window said: `'explorer.exe' (Win32): Unloaded 'C:\Users\Adam\Documents\Projects\Solution\x64\Debug\ShExt.dll'`, which is my extension. –  May 08 '20 at 21:11

0 Answers0