gpt4 book ai didi

c# - 如何使用 Windows 运行时通过 C# 实现 C++ API?

转载 作者:太空狗 更新时间:2023-10-29 21:56:15 28 4
gpt4 key购买 nike

我正在使用一个 native C++ 应用程序,它有一个插件系统,它将在 .dll 上使用 LoadLibrary()/GetProcAddress() 来调用函数。我想实现这些插件之一,并且在插件内部我想使用持久性框架将复杂的对象图保存/加载到磁盘。

Windows 上支持最多的 ORM 似乎是 Entity Framework,而 this page说 Entity Framework Core 是最现代的风格。 This page似乎是说,为了使用 Entity Framework Core,您的数据模型必须用 C# 编写。

所以,听起来我必须从 C++ 调用 C#。幸运的是,它看起来像 Entity Framework Core supports通用 Windows 运行时,它应该使语言之间的调用变得容易。

This presentation似乎是说从 C++ 与通用 Windows 运行时交互涉及创建 Windows 运行时组件,编译步骤可以从 Windows 运行时组件的 .winmd 文件生成胶水代码。

因此,我可以制作一个包含两个项目的 Visual Studio 解决方案:一个外部“C++ Windows 桌面动态链接库”项目和一个内部“C# 通用 Windows 运行时组件”。

Outer C++ Windows Desktop Dynamic-Link Library Inner C# Universal Windows Runtime Component

docs然后说“引用 Windows 运行时组件的 Windows 运行时元数据 (.winmd) 文件,然后构建”。但是,当我在外部项目中添加引用时,当我尝试选择内部项目时出现错误,并且没有浏览选择任意 .winmd 的选项。

Error when trying to add a reference to inner project

即使我进入解决方案管理器并删除两个项目中除 x86 之外的所有平台,也会发生此错误。

这令人惊讶,因为 this Windows Blog post明确表示 native 代码应该能够通过添加对 .winmd 的引用来调用 UWP 代码(尽管该帖子使用较旧的 C++/CX 语法)。

如果我重新开始并使用“C++/WinRT Windows 运行时组件”而不是“C++ Windows 桌面动态链接库”项目,我仍然遇到问题。

Outer C++/WinRT Windows Runtime Component

如果我这样做,我可以很好地添加引用。

Successful Reference

但是,当我尝试构建时,构建失败。

1>------ Build started: Project: InnerCSharp, Configuration: Debug x86 ------
1> InnerCSharp -> C:\Users\lithe\source\repos\EntityFrameworkInsideC++\InnerCSharp\bin\x86\Debug\InnerCSharp.winmd
2>------ Build started: Project: OuterC++WinRT, Configuration: Debug Win32 ------
2>MIDLRT Processing C:\Users\lithe\source\repos\EntityFrameworkInsideC++\OuterC++WinRT\Class.idl
2>Class.idl
2>MIDLRT Processing C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\winrt\winrtbase.idl
2>winrtbase.idl
2>MIDLRT Processing C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\winrt\midlbase.idl
2>midlbase.idl
2>Processing WinMD c:\users\lithe\source\repos\entityframeworkinsidec++\innercsharp\bin\x86\debug\innercsharp.winmd
2>Processing WinMD c:\program files (x86)\windows kits\10\references\10.0.17134.0\windows.ai.machinelearning.preview.machinelearningpreviewcontract\1.0.0.0\windows.ai.machinelearning.preview.machinelearningpreviewcontract.winmd
... snip ...
2>Processing WinMD c:\program files (x86)\windows kits\10\references\10.0.17134.0\windows.ui.viewmanagement.viewmanagementviewscalingcontract\1.0.0.0\windows.ui.viewmanagement.viewmanagementviewscalingcontract.winmd
2>MDMERGE : error MDM2006: C:\Users\lithe\source\repos\EntityFrameworkInsideC++\InnerCSharp\bin\x86\Debug\InnerCSharp.winmd does not appear to be a valid Windows Runtime metadata file
2>MDMERGE : error MDM2005: Unable to open metadata file C:\Users\lithe\source\repos\EntityFrameworkInsideC++\InnerCSharp\bin\x86\Debug\InnerCSharp.winmd.
2>Microsoft(R) Metadata Merge Utility Version 10.0.45.
2>
2>
2>Creating output directory C:\Users\lithe\source\repos\EntityFrameworkInsideC++\Debug\OuterC++WinRT\Merged.
2>Load input metadata file C:\Users\lithe\source\repos\EntityFrameworkInsideC++\InnerCSharp\bin\x86\Debug\InnerCSharp.winmd.
2>Load input metadata file C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract\1.0.0.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract.winmd.
... snip ...
2>Load input metadata file C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract\1.0.0.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract.winmd.
2>Processing input metadata file C:\Users\lithe\source\repos\EntityFrameworkInsideC++\Debug\OuterC++WinRT\Unmerged\Class.winmd.
2>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.Cpp.CppWinRTEnabled.targets(244,9): error MSB3073: The command "mdmerge.exe -v -metadata_dir "C:\Users\lithe\source\repos\EntityFrameworkInsideC++\InnerCSharp\bin\x86\Debug\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract\1.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.ApplicationModel.Calls.CallsVoipContract\3.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract\2.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.ApplicationModel.StartupTaskContract\3.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Devices.Custom.CustomDeviceContract\1.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Devices.DevicesLowLevelContract\3.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Devices.Printers.PrintersContract\1.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract\3.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Devices.SmartCards.SmartCardEmulatorContract\5.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Foundation.FoundationContract\3.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Foundation.UniversalApiContract\6.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Gaming.XboxLive.StorageApiContract\1.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Graphics.Printing3D.Printing3DContract\4.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Networking.Connectivity.WwanContract\2.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Services.Store.StoreContract\3.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.Services.TargetedContent.TargetedContentContract\1.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.System.Profile.ProfileHardwareTokenContract\1.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.System.Profile.ProfileSharedModeContract\2.0.0.0\." -metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.17134.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract\1.0.0.0\." -o "C:\Users\lithe\source\repos\EntityFrameworkInsideC++\Debug\OuterC++WinRT\Merged" -i "C:\Users\lithe\source\repos\EntityFrameworkInsideC++\Debug\OuterC++WinRT\Unmerged" -partial" exited with code 2.
2>Done building project "OuterC++WinRT.vcxproj" -- FAILED.
========== Build: 1 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

但是,我可以按照 the earlier presentation 中的步骤操作在 C++/WinRT Windows 运行时项目(无需任何额外配置)和 ComponentC++ Windows 桌面动态链接库项目(并运行 cppwinrt 命令行工具,如 this answer 中所述)中成功引用 Win2D。但是,这对我没有帮助——我不是要引用 NuGet 包;我试图在同一个解决方案中引用不同的项目。

所以,毕竟,问题是:如何使用通用 Windows 运行时从 C++ 代码调用 C# 代码?

最佳答案

您不能从 Windows 桌面应用程序调用 Windows 运行时组件。此功能是为通用 Windows 平台 (UWP) 应用程序保留的。通过使用 RoGetActivationFactory 访问/实例化/调用 Windows 运行时类型函数,并且该函数仅采用类名,而不是类名和类所在的 DLL。这意味着系统必须能够定位类所在的位置。对于系统 API,这很容易——它们被硬编码在 Windows 注册表中。对于 Windows 运行时组件中的自定义类,它依赖于 AppX list 来告知哪些类位于哪些 DLL 中。遗憾的是,对于桌面应用程序,您没有 AppX list ,因此您无法调用自定义类。

还有其他(和更好的)方法可以从您的桌面应用程序调用托管代码。

一种选择是使用 /clr在构建 DLL 时标记。这将创建一个可以直接调用 C# 代码的 DLL。

另一种选择是托管 CLR in your process manually and invoke code that way .

我的回答假设您的应用程序以 Windows 桌面为目标而不是 UWP,因为您的第一个 DLL 以桌面为目标。如果不是这种情况,Windows 运行时组件可能是一个解决方案,但为这种设置设置生成管道并不是很简单。您看到的错误来自 C++/winrt 编译器,它会尝试将 .winmd 文件转换为头文件。我不知道它为什么会失败,但您应该能够通过使用常规 Windows 运行时组件模板(而不是 C++/winrt 模板)来禁用它。

关于c# - 如何使用 Windows 运行时通过 C# 实现 C++ API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52434751/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com