C# 如何从C++;后台任务(Windows通用应用程序)?

C# 如何从C++;后台任务(Windows通用应用程序)?,c#,c++,windows-runtime,windows-phone-8.1,win-universal-app,C#,C++,Windows Runtime,Windows Phone 8.1,Win Universal App,我正在将我的应用程序(使用自定义live tiles)重写为通用应用程序。以前,我使用第三方库来渲染这些定制的实时平铺。这个库不再受支持,所以我必须找到一种新的方法来实现这一点。看来这是目前唯一的出路,但这是在C++。我的应用程序的其余部分是C# 我的后台任务应该从公共API(例如天气)获取数据,并使用这些信息渲染实时互动程序。我已经编写了用于获取数据的类(我也在主应用程序中使用它们),但这些类是用C#编写的 现在,使用Windows运行时组件,应该可以“混合”不同的语言(对吗?)。但我如何做到

我正在将我的应用程序(使用自定义live tiles)重写为通用应用程序。以前,我使用第三方库来渲染这些定制的实时平铺。这个库不再受支持,所以我必须找到一种新的方法来实现这一点。看来这是目前唯一的出路,但这是在C++。我的应用程序的其余部分是C#

我的后台任务应该从公共API(例如天气)获取数据,并使用这些信息渲染实时互动程序。我已经编写了用于获取数据的类(我也在主应用程序中使用它们),但这些类是用C#编写的

现在,使用Windows运行时组件,应该可以“混合”不同的语言(对吗?)。但我如何做到这一点?(缺少混凝土样品)

< > > <强>我如何调用C++函数(将返回数据)从C++背景任务< /强>?/p> <>我创建了一个非常好的示例——我想从C++后台任务运行RunTew函数和RunAsOffice函数。
public class StackOverFlowExampleClass()
{
    public string Name { get; set; }
    public string Value { get; set; }
}

public class StackOverFlowExampleClass2()
{
    public string UpperString { get; set; }

}

public async Task<StackOverFlowExampleClass> RunTheFunction(int ParameterValue)
{
    StackOverFlowExampleClass overflowClass = new StackOverFlowExampleClass();
    overflowClass.Name = "Stack Overflow";
    overflowClass.Value = 1 + ParameterValue;

    // DO SOME COOL ADVANCED HTTP STUFF
    return overflowClass;
}

public async Task<StackOverFlowExampleClass> RunAnotherFunction(string ExampleString)
{
    StackOverFlowExampleClass2 overflowClass2 = new StackOverFlowExampleClass2();
    overflowClass2.UpperString = ExampleString.ToUpper();

    return overflowClass2;
}
<如何在C++中实现这一点? 您可以查看一些漂亮的示例,例如: __等待FileIO::WriteTextAsync(文件,文件->名称)


它看起来还不太好,未来版本中可能会出现标准的、不断发展的、新的和更好的(至少是标准的)实现方法。

您可以尝试使用COM实现这一点(尽管我不确定它是否适合):

C侧:

您必须采用C++代码,并生成一个程序集、清单和TLB文件,导入到C++代码中。 C++方面:

using namespace CSharpCOM;
ICSharpFunctorPtr pCSharp;
HRESULT hr = pCSharp.CreateInstance(__uuidof(CSharpFunctor));
assert(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
    IExampleClassPtr e1 = pCSharp->RunTheFunction(10);
    assert(e1->Value == 11);
    std::string name = e1->Name;
    assert(name == "Stack Overflow");
    IExampleClass2Ptr e2 = pCSharp->RunAnotherFunction("stackoverflow");
    std::string uc = e2->UpperString;
    assert(uc == "STACKOVERFLOW");
}
下面是一个完整示例的链接(包括我错过的一些关于接口的内容)
您有几个选择:

  • 将C#代码移动到Windows运行时组件中
  • 为C代码创建包装器Windows运行时组件
  • 使C++代码成为Windows运行时组件。
  • 为C++代码创建包装窗口运行时组件。

    在你完成其中一个之后,你可以使用C++中的组件,C语言或JavaScript,如果它是用你所使用的语言编写的。


    用C语言构建Windows运行时组件++

    在C#和Visual Basic中创建Windows运行时组件

    在C语言中创建Windows运行时组件++


    数字4的一个很好的例子是SQLite WinRT,可以在这里找到它

    您有什么原因不能用C#编写您的后台任务并从此调用XamlRenderingBackgroundTask吗?由于内存问题,不建议这样做。这里有一个样本,但没有成功。。代码生成了一个损坏的映像。但这不意味着你的整个问题都是“由于内存问题而不推荐使用”吗?我刚才说的是生成磁贴。。这就是占用内存的东西。如果后台任务是C++(并进行渲染),那么我想我会很好的。谢谢你的回答。我尝试了您的步骤,但生成tlb文件时遇到了问题。为此,我必须在项目属性中启用“注册COM互操作”,但此复选框变灰。输出类型设置为“类库”。您不必启用它。我创建了一个COM项目,但没有使用它。您可以设置清单,以便不必注册程序集。您正在使用哪个版本的visual studio?我可以把一个小例子放在我的github上。我已经更新了答案,包含了完整工作示例的链接。我已经安装了它,你能举个例子说明如何使用上面提到的代码吗?我对如何使用它感到困惑:(
    using System;
    using System.Runtime.InteropServices;
    
    namespace CSharp
    {
        [Guid("62D276EB-FABE-4c0e-BF59-7D0799DEC029")]
        [ComVisible(true)]
        public interface IExampleClass
        {
            string Name { get; set; }
            int Value { get; set; }
        }
    
        [ClassInterface(ClassInterfaceType.None)]
        [Guid("4E196599-F1C5-4447-84F4-E46FC1C16105")]
        [ComVisible(true)]
        public class ExampleClass : IExampleClass
        {
            public ExampleClass()
            { }
    
            public string Name { get; set; }
            public int Value { get; set; }
        }
    
        [Guid("72D276EB-FABE-4c0e-BF59-7D0799DEC020")]
        [ComVisible(true)]
        public interface IExampleClass2
        {
            string UpperString { get; set; }
        }
    
        [ClassInterface(ClassInterfaceType.None)]
        [Guid("6712709D-8913-4911-8ABB-BFB4865D4E9F")]
        [ComVisible(true)]
        public class ExampleClass2 : IExampleClass2
        {
            public ExampleClass2()
            { }
    
            public string UpperString { get; set; }
        }
    
        [Guid("1C312E27-6B09-412c-B7AA-55F4E0FBCF8C")]
        [ComVisible(true)]
        public interface ICSharpFunctor
        {
            ExampleClass RunTheFunction(int ParameterValue);
            ExampleClass2 RunAnotherFunction(string ExampleString);
        }
    
        [ClassInterface(ClassInterfaceType.None)]
        [Guid("9B8FAFEA-64EB-493f-95CB-B0B0EDEBADC2")]
        [ComVisible(true)]
        public class CSharpFunctor : ICSharpFunctor
        {
            public CSharpFunctor()
            { }
    
            public ExampleClass RunTheFunction(int ParameterValue)
            {
                ExampleClass instance = new ExampleClass();
                instance.Name = "Stack Overflow";
                instance.Value = 1 + ParameterValue;
                return instance;
            }
    
            public ExampleClass2 RunAnotherFunction(string ExampleString)
            {
                ExampleClass2 instance = new ExampleClass2();
                instance.UpperString = ExampleString.ToUpper();
                return instance;
            }
        }
    }
    
    using namespace CSharpCOM;
    ICSharpFunctorPtr pCSharp;
    HRESULT hr = pCSharp.CreateInstance(__uuidof(CSharpFunctor));
    assert(SUCCEEDED(hr));
    if (SUCCEEDED(hr))
    {
        IExampleClassPtr e1 = pCSharp->RunTheFunction(10);
        assert(e1->Value == 11);
        std::string name = e1->Name;
        assert(name == "Stack Overflow");
        IExampleClass2Ptr e2 = pCSharp->RunAnotherFunction("stackoverflow");
        std::string uc = e2->UpperString;
        assert(uc == "STACKOVERFLOW");
    }