如何从 C++ 后台任务(Windows 通用应用程序)调用 C# 函数?
Posted
技术标签:
【中文标题】如何从 C++ 后台任务(Windows 通用应用程序)调用 C# 函数?【英文标题】:How to call C# function from C++ background task (Windows Universal app)? 【发布时间】:2014-07-23 12:16:48 【问题描述】:我正在将我的应用(使用自定义动态磁贴)重写为通用应用。以前,我使用 3rd 方库来渲染这些自定义动态磁贴。不再支持这个库,所以我必须找到一种新的方法来做到这一点。似乎XamlRenderingBackgroundTask 是目前唯一的前进方向,但这是在 C++ 中。我的应用程序的其余部分在 C# 中。
我的后台任务应该从公共 API 获取数据(例如天气),并使用这些信息来呈现动态磁贴。我已经编写了获取数据的类(我也在主应用程序中使用它们),但这些是用 C# 编写的。
现在,使用 Windows 运行时组件应该可以“混合”不同的语言(对吗?)。但是我该如何实现呢? (缺少具体样品)。
简而言之:如何从我的 C++ 后台任务调用 C# 函数(将返回数据)?
我创建了一个非常示例 - 我想从我的 C++ 后台任务中运行 RunTheFunction 和 RunAnotherFunction。
public class ***ExampleClass()
public string Name get; set;
public string Value get; set;
public class ***ExampleClass2()
public string UpperString get; set;
public async Task<***ExampleClass> RunTheFunction(int ParameterValue)
***ExampleClass overflowClass = new ***ExampleClass();
overflowClass.Name = "Stack Overflow";
overflowClass.Value = 1 + ParameterValue;
// DO SOME COOL ADVANCED HTTP STUFF
return overflowClass;
public async Task<***ExampleClass> RunAnotherFunction(string ExampleString)
***ExampleClass2 overflowClass2 = new ***ExampleClass2();
overflowClass2.UpperString = ExampleString.ToUpper();
return overflowClass2;
在正常的 C# 后台任务中,我会这样做:
***ExampleClass SFClass = await ***example.RunTheFunction(10);
***ExampleClass2 SFClass = await ***example.RunAnotherFunction("***");
///// render SFClass.Value + SFClass.Name as a PNG
///// set tile title to SFClass.UpperString
如何在 C++ 中做到这一点?
【问题讨论】:
有什么理由不能用 C# 编写后台任务并从中调用 XamlRenderingBackgroundTask 吗? 由于内存问题,不建议这样做。这里有一个示例:social.msdn.microsoft.com/Forums/en-US/… 但它没有成功。代码生成了一个损坏的图像。 但这是否意味着您的整个问题“由于内存问题不推荐”? 我说的是生成图块。这就是占用内存的原因。如果后台任务在 C++ 中(并进行渲染),那么我想我会没事的。 【参考方案1】:您可以查看Visual C++ Compiler November 2013 CTP,一些漂亮的示例可以执行以下操作: __await FileIO::WriteTextAsync(file, file->Name);
它看起来还不是很好,而且很可能会在未来的版本中出现标准的发展、新的和更好的(至少是标准的)方法。
【讨论】:
我已经安装了,你能举个例子说明如何使用上面提到的代码吗?我对如何使用它感到困惑:(【参考方案2】:您可以尝试为此使用 COM(虽然我不确定它是否合适):
C#端:
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;
您必须获取 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("***");
std::string uc = e2->UpperString;
assert(uc == "***");
这是一个完整示例的链接(包括我错过的有关接口的一些内容。) https://github.com/brandon-kohn/CSharpCOM
【讨论】:
感谢您的回答。我尝试了您的步骤,但在生成 tlb 文件时遇到了困难。为此,我必须在项目属性中启用“注册 COM 互操作” - 但此复选框是灰色的。输出类型设置为“类库”。 您不必启用它。我创建了一个不使用它的 COM 项目。您可以设置清单,这样您就不必注册程序集。您使用的是哪个版本的视觉工作室?我可以把一个小例子放在我的 github 上。 我已更新答案以包含指向完整工作示例的链接。【参考方案3】:你有几个选择:
-
将 C# 代码移动到 Windows 运行时组件中。
为 C# 代码创建一个包装 Windows 运行时组件
使 C++ 代码成为 Windows 运行时组件。
为 C++ 代码创建一个包装 Windows 运行时组件。
完成其中一项后,您可以在 C++、C# 或 javascript 中使用该组件,前提是它是用您使用的语言编写的。
使用 C++ 构建 Windows 运行时组件
http://channel9.msdn.com/events/Windows-Camp/Developing-Windows-8-Metro-style-apps-in-Cpp/Building-Windows-Runtime-Components-with-Cpp
在 C# 和 Visual Basic 中创建 Windows 运行时组件
http://msdn.microsoft.com/en-us/library/br230301.aspx
在 C++ 中创建 Windows 运行时组件
http://msdn.microsoft.com/en-us/library/hh441569.aspx
4 号的一个很好的例子是 SQLite-WinRT,可以在这里找到http://sqlwinrt.codeplex.com/
【讨论】:
以上是关于如何从 C++ 后台任务(Windows 通用应用程序)调用 C# 函数?的主要内容,如果未能解决你的问题,请参考以下文章
用于获取通知的通用 Windows 10 应用后台任务计时器
可以运行 2 个后台任务 - Windows Phone 8.1 通用应用程序?
是否可以在 WinRT/Windows 通用应用程序的后台任务中检索手机电池状态?