Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows::Storage::ApplicationData::Current Not Found in C++

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.

enter image description here

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
    }
like image 387
Cheok Yan Cheng Avatar asked Feb 18 '23 20:02

Cheok Yan Cheng


1 Answers

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.

like image 170
James McNellis Avatar answered Feb 26 '23 23:02

James McNellis