Как можно ссылаться на компонент среды выполнения Windows, написанный на C++, из библиотеки классов, написанной на C#?

Я работаю над проектом WP8, который включает проект библиотеки классов в виде исходного кода C# и компонент среды выполнения Windows в виде исходного кода C++. Кто-нибудь знает, можно ли создать такую ​​библиотеку классов С#, которая будет ссылаться на компонент среды выполнения Windows? Конечным результатом должна быть сборка .NET и компонент среды выполнения .WIMND/.DLL, который можно использовать для приложения. В настоящее время я не могу создать библиотеку классов, потому что она не видит компонент среды выполнения Windows, хотя я добавил его в проект.

Более конкретно. У меня есть, скажем, MyNs.MyClass.MyMethod(), который определен в компоненте среды выполнения C++ и используется из библиотеки классов C#. В настоящее время я не могу скомпилировать С# из-за отсутствия метода, хотя у меня есть проект компонента среды выполнения Windows, прикрепленный к тому же решению.


person user3507069    schedule 06.02.2015    source источник
comment
Project + Add References, узел Solution, отметьте свой проект C++.   -  person Hans Passant    schedule 06.02.2015
comment
Библиотека классов или портативная библиотека классов? И если второе, то какие цели вы выбрали?   -  person Peter Torr - MSFT    schedule 06.02.2015
comment
Я выбрал библиотеку классов (Windows Phone 8.0). Во всяком случае, я решил это, вручную добавив ссылку на файл .winmd.   -  person user3507069    schedule 09.02.2015


Ответы (3)


Хотя я вмешиваюсь, потому что это не моя область, я попробовал поискать в Google «компонент среды выполнения c# для вызова Windows». Кажется, есть много хитов/примеров, например. первый — https://msdn.microsoft.com/en-us/library/hh755833.aspx.

Вам это не помогает?

person JonBrave    schedule 06.02.2015
comment
К сожалению нет. В большинстве этих примеров объясняется, как вызывать компонент из приложения. В моем случае это не приложение, это библиотека классов, которую необходимо доставить в виде DLL сборки .NET. - person user3507069; 06.02.2015
comment
Понял, извините, не помогло. Учитывая это, возможно, вы могли бы добавить библиотеку классов или аналогичные теги этого вопроса? - person JonBrave; 06.02.2015

Я решил это, добавив ссылку на компонент среды выполнения Windows вручную в файл .csproj библиотеки классов С# следующим образом.

...
    <ItemGroup>
        <Reference Include="WindowsRuntimeComponent.winmd" />
    </ItemGroup>
...
person user3507069    schedule 07.02.2015
comment
Где был файл .winmd по отношению к .csproj? Был ли это единственный шаг или это было дополнением к добавлению .winmd в раздел ссылок? - person Zak; 22.02.2015
comment
Компонент среды выполнения Windows состоит из двух частей — собственной библиотеки DLL и кода-оболочки WINMD, который сопоставляет собственную часть с управляемыми интерфейсами. Только для компиляции достаточно поместить WINMD в ту же папку, где находится DLL библиотеки классов C#. Для правильного функционирования все три компонента должны находиться в одной папке - DLL библиотеки классов C#, управляемая часть C++/CX WINMD и собственная DLL C++/CX. - person user3507069; 25.02.2015
comment
Некоторые пояснения к предыдущему комментарию: файлы .winmd не содержат кода (обертки). Они содержат только метаданные, повторно используя формат файла .NET. Компилятор использует метаданные для создания кода для доступа к компоненту среды выполнения Windows. - person IInspectable; 16.06.2016

Мне удалось создать проект C++ WRL и использовать класс в этом проекте из проекта C#, добавив ссылку обычным способом. Проект Wrl (не C++/CX, который тоже работает) был создан с использованием некоторого шаблона WRL, который я нашел где-то в Интернете. Проект wrl потребовал от меня создания .idl для определения интерфейса и создания его .dll и .winmd. Вот некоторый код для тех, кто борется с такими вещами:

Класс WRL:

#include "pch.h"

#include "WrlTestClass2_h.h"
#include <wrl.h>

using namespace Microsoft::WRL;
using namespace Windows::Foundation;

namespace ABI
{
    namespace WrlTestClass2
    {
        class WinRTClass: public RuntimeClass<IWinRTClass>
        {
            InspectableClass(RuntimeClass_WrlTestClass2_WinRTClass, BaseTrust)

            public:
            WinRTClass()
            {
            }

            // http://msdn.microsoft.com/en-us/library/jj155856.aspx
            // Walkthrough: Creating a Basic Windows Runtime Component Using WRL
            HRESULT __stdcall Add(_In_ int a, _In_ int b, _Out_ int* value)
            {
                if (value == nullptr)
                {
                    return E_POINTER;
                }
                *value = a + b;
                return S_OK;
            }

        };

        ActivatableClass(WinRTClass);
    }
}

Код C#, использующий этот класс:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;


namespace CSharpClientToWrl
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            WrlTestClass2.WinRTClass _winRtTestClass = new WrlTestClass2.WinRTClass();

            int _answer = _winRtTestClass.Add(4, 6);

            Assert.AreEqual(_answer, 10);
        }
    }
}

Файл .idl проекта wrl:

import "inspectable.idl"; import "Windows.Foundation.idl";

#define COMPONENT_VERSION 1.0

namespace WrlTestClass2 {
    interface IWinRTClass;
    runtimeclass WinRTClass;

    [uuid(0be9429f-2c7a-40e8-bb0a-85bcb1749367), version(COMPONENT_VERSION)] 
    interface IWinRTClass : IInspectable
    {       // http://msdn.microsoft.com/en-us/library/jj155856.aspx        // Walkthrough: Creating a Basic Windows Runtime Component Using WRL        HRESULT Add([in] int a, [in] int b, [out, retval] int* value);
    }

    [version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]
    runtimeclass WinRTClass
    {
        [default] interface IWinRTClass;
    } }
person Elliot    schedule 07.04.2015