Windows::Storage::ApplicationData::Current Not Fou

2019-06-24 10:52发布

问题:

My C++ code, which is part of Media Foundation Transform tend to able to run in Windows Store App (Metro)

I modify the C++ GrayscaleTransform to include the following code.

However, my C++ code fails to locate namespace Windows::Storage.

LPCWSTR zPath = Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data();

Is there any additional settings I need to do?

I can make it compiled, by turning on Consume Windows Runtime Extension.

But by doing this, it will give me additional linking error and warnings.

warning LNK4197: export 'DllGetActivationFactory' specified multiple times; using first specification 
warning LNK4197: export 'DllCanUnloadNow' specified multiple times; using first specification
warning LNK4197: export 'DllGetActivationFactory' specified multiple times; using first specification 
warning LNK4197: export 'DllCanUnloadNow' specified multiple times; using first specification
error LNK2005: _DllCanUnloadNow@0 already defined in dllmain.obj 
error LNK1169: one or more multiply defined symbols found

Comment out DllCanUnloadNow will produce runtime error.

I get a runtime break at

// GrayscaleTransform.dll!Microsoft::WRL::Details::ModuleBase::ModuleBase()  Line 155 + 0x46 bytes  C++

    ModuleBase() throw()
    {
#ifdef _DEBUG
        // This indicates that there were two instances of the module created or race conditon during module creation
        // If you are creating object with new/delete please make sure that you haven't created more than one module 
        // and you disabled static initalization with __WRL_DISABLE_STATIC_INITIALIZE__
        // otherwise please initialize/create module in main()
        __WRL_ASSERT__(::InterlockedCompareExchangePointer(reinterpret_cast<void* volatile*>(&module_), this, nullptr) == nullptr &&
            "The module was already instantiated");

        SRWLOCK initSRWLOCK = SRWLOCK_INIT;
        __WRL_ASSERT__(reinterpret_cast<SRWLOCK*>(&moduleLock_)->Ptr == initSRWLOCK.Ptr && "Different value for moduleLock_ than SRWLOCK_INIT");
        (initSRWLOCK);
#else
        module_ = this;
#endif
    }

回答1:

The linker errors occur because you enabled C++/CX in the GrayscaleTransform project. Your project defines the listed entry points in dllmain.cpp. When you enable C++/CX, vccorlib gets linked into your module, and it also defines these entry points.

The runtime error occurs because the C++/CX infrastructure in vccorlib creates a Module, and your entry point tries to create a different kind of Module. There can only be one Module in a module.

You need to make a few more changes to the GrayscaleTransform project to be able to use C++/CX in it:

  • Remove the four Dll*() functions from dllmain.cpp. You will rely instead on the definitions linked in from vccorlib. Note that the class registration (ActivatableClass(CGrayscale)) is still required.

  • In the C++ Preprocessor options, ensure that _WINRT_DLL is defined in the "Preprocessor Definitions."

  • In the Linker input options, remove the "Module Definition File."

Note that you will need to be very careful when mixing C++/CX and "low-level" C++ using WRL. Most expressions that involve C++/CX types can throw exceptions, and you must ensure that no exceptions are ever allowed to cross the ABI boundary.

Alternatively, consider not using C++/CX and instead using WRL throughout your project. It will be more verbose, but if you are already using WRL for other parts of the project, it may make more sense.