2014-10-30 79 views
-1

我是一名C#技术人员,拥有关于C++-cli的知识。如何制作用于C#的C++ -cli Windows运行时组件?

我想将以下代码(as seen here)作为Windows Runtime C++ -cli组件在我的C#项目中使用。

我创建了一个C++ - cli Windows运行时组件,然后将代码粘贴到一个新类中。但是出现了这些错误。

我该如何解决前两个错误?谢谢。

enter image description here

public ref class AlbumArtReader sealed 
{ 
public: 
    AlbumArtReader(); 
    virtual ~AlbumArtReader(); 

    void Initialize(Windows::Storage::Streams::IRandomAccessStream^ stream); 
    Windows::Foundation::IAsyncOperation<Windows::Storage::Streams::InMemoryRandomAccessStream^>^ GetAlbumArtAsync(); 

private: 
    void InitializeCommon(); 

private: 
    Microsoft::WRL::ComPtr<IMFSourceReader> m_pSourceReader; 
}; 

AlbumArtReader::AlbumArtReader() 
{ 
    HRESULT hr = ::MFStartup(MF_VERSION); 
    ThrowIfFailed(hr); 
} 

AlbumArtReader::~AlbumArtReader() 
{ 
    HRESULT hr = ::MFShutdown(); 
    if (FAILED(hr)) TRACEMESSAGEA("MFShutdown failed"); 
} 

void AlbumArtReader::Initialize(Windows::Storage::Streams::IRandomAccessStream^ stream) 
{ 
    HRESULT hr; 

    ComPtr<IUnknown> pStreamUnk = reinterpret_cast<IUnknown*>(stream); 
    ComPtr<IMFByteStream> pMFStream; 
    hr = ::MFCreateMFByteStreamOnStreamEx(pStreamUnk.Get(), &pMFStream); 
    ThrowIfFailed(hr); 

    hr = ::MFCreateSourceReaderFromByteStream(pMFStream.Get(), NULL, &m_pSourceReader); 
    ThrowIfFailed(hr); 
} 

Windows::Foundation::IAsyncOperation<Windows::Storage::Streams::InMemoryRandomAccessStream^>^ 
AlbumArtReader::GetAlbumArtAsync() 
{ 
    return concurrency::create_async([this]() 
    { 
     try 
     { 
      HRESULT hr; 

      ComPtr<IMFMediaSource> pMediaSource; 
      hr = m_pSourceReader->GetServiceForStream(MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pMediaSource)); 
      ThrowIfFailed(hr); 

      ComPtr<IMFGetService> pGetService; 
      hr = pMediaSource.As(&pGetService); 
      ThrowIfFailed(hr); 

      ComPtr<IMFMetadataProvider> pMetadataProvider; 
      hr = pGetService->GetService(MF_METADATA_PROVIDER_SERVICE, IID_PPV_ARGS(&pMetadataProvider)); 
      ThrowIfFailed(hr); 

      ComPtr<IMFPresentationDescriptor> pPresentationDescriptor; 
      hr = pMediaSource->CreatePresentationDescriptor(&pPresentationDescriptor); 
      ThrowIfFailed(hr); 

      ComPtr<IMFMetadata> pFileMetadata; 
      hr = pMetadataProvider->GetMFMetadata(pPresentationDescriptor.Get(), 0, 0, &pFileMetadata); 
      ThrowIfFailed(hr); 

      PROPVARIANT propVar; 
      PropVariantInit(&propVar); 
      hr = pFileMetadata->GetProperty(L"WM/Picture", &propVar); 

      if (SUCCEEDED(hr) && propVar.vt == VT_BLOB && propVar.blob.cbSize != 0) 
      { 
       BYTE *pData = propVar.blob.pBlobData; 
       ULONG nData = propVar.blob.cbSize; 

       // ASF_FLAT_PICTURE 
       BYTE bPictureType = pData[0]; 
       pData += sizeof(BYTE); 
       nData -= sizeof(BYTE); 
       DWORD dwDataLen = 0; 
       memcpy(&dwDataLen, pData, sizeof(DWORD)); 
       pData += sizeof(DWORD); 
       nData -= sizeof(DWORD); 

       // MIME type 
       WCHAR *szBegin = (WCHAR*)pData; 
       ULONG nsz = nData/sizeof(WCHAR); 
       WCHAR *szEnd = std::find(szBegin, szBegin + nsz, L'\0'); 
       ThrowIfFailed(szEnd != szBegin + nsz, L"Failed to find mime type in blob data"); 

       std::wstring mimeType(szBegin, szEnd); 
       nsz -= ((ULONG)mimeType.length() + 1); 

       // description  
       szBegin = szEnd + 1; 
       szEnd = std::find(szBegin, szBegin + nsz, L'\0'); 
       ThrowIfFailed(szEnd != szBegin + nsz, L"Failed to find description in blob data"); 

       std::wstring description(szBegin, szEnd); 
       nsz -= ((ULONG)description.length() + 1); 
       pData = (BYTE*)(szEnd + 1); 
       nData = nsz * sizeof(WCHAR); 

       // Image data 
       Platform::ArrayReference<BYTE> dataRef(pData, nData); 

       auto metaDataStream = ref new Windows::Storage::Streams::InMemoryRandomAccessStream(); 
       auto dataWriter = ref new Windows::Storage::Streams::DataWriter(metaDataStream->GetOutputStreamAt(0)); 
       dataWriter->WriteBytes(dataRef); 

       return concurrency::create_task(dataWriter->StoreAsync()) 
        .then([dataWriter, metaDataStream](unsigned int bytesStored) 
        { 
         return dataWriter->FlushAsync(); 
        }).then([dataWriter, metaDataStream](bool flushOp) 
        { 
         dataWriter->DetachStream(); 
         return metaDataStream; 
        }); 
      } 
     } 
     catch (Platform::Exception^ ex) 
     { 
      TRACEMESSAGEW(L"HR exception caught in AlbumArtReader::GetAlbumArtAsync(): %s\n", ex->ToString()->Data()); 
     } 
     catch (...) 
     { 
      TRACEMESSAGEA("unknown exception caught in AlbumArtReader::GetAlbumArtAsync()\n"); 
     } 

     return concurrency::create_task([]()->Windows::Storage::Streams::InMemoryRandomAccessStream^ { return nullptr; }); 
    }); 
} 
+0

我认为它叫什么货?码。总之有一个维基百科,你应该查找它。 – RadioSpace 2014-10-30 01:50:44

+0

@RadioSpace货物崇拜编程:))我知道这样问这样的问题很愚蠢,但是我很坏! – user3293835 2014-10-30 02:07:48

+0

不要在'ref class'之前公开' – ArthurCPPCLI 2014-10-30 09:48:42

回答

1

所有WinRT的类型必须命名空间内。输出winmd文件的名称必须是您的名称空间名称的前缀。例如,如果您创建的项目名为“MyProject”,那么您需要将这些类型放入名为MyProject的名称空间(可选地带有一些子名称空间)中。

namespace MyProject 
{ 
    public ref class Foo sealed 
    { 
    // 
    }; 
} 

有两点需要注意:

  1. 您的命名空间不能以开头的 “Windows”。 - 那是保留给OS
  2. 这不是C++/CLI,它是C++/CX
+0

感谢Peter @PeterTorr – user3293835 2014-10-31 05:53:34