如何制作C ++ - cli Windows运行时组件用于C#

时间:2014-10-30 01:40:38

标签: c# windows-phone-8 windows-runtime c++-cli

我是一个C#人,对C ++有着技术上的零知识 - cli。

我想将以下代码(as seen here)作为Windows运行时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; });
    });
}

1 个答案:

答案 0 :(得分:1)

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

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

两个注释:

  1. 您的命名空间不能以“Windows”开头。 - 为操作系统保留
  2. 这不是C ++ / CLI,而是C ++ / CX