加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

如何使用Windows运行时使用C#实现C API?

发布时间:2020-12-14 02:47:50 所属栏目:Windows 来源:网络整理
导读:我正在使用一个带有插件系统的本机C app,它会在.dll上调用LoadLibrary()/ GetProcAddress()来调用函数.我想实现其中一个插件,在插件中我想使用持久性框架来保存/加载一个复杂的对象图到磁盘. 似乎Windows上支持最多的ORM是实体框架,而this page表示实体框架
我正在使用一个带有插件系统的本机C app,它会在.dll上调用LoadLibrary()/ GetProcAddress()来调用函数.我想实现其中一个插件,在插件中我想使用持久性框架来保存/加载一个复杂的对象图到磁盘.

似乎Windows上支持最多的ORM是实体框架,而this page表示实体框架核心是最现代的风格. This page似乎说,为了使用Entity Framework Core,您的数据模型必须用C#编写.

所以,听起来我必须从C调用C#.幸运的是,似乎Entity Framework Core supports是通用Windows运行时,它应该可以轻松地在语言之间进行调用.

This presentation似乎说与C的Universal Windows Runtime交互涉及创建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明确表示本机代码应该能够通过添加对.winmd的引用来调用UWP代码(尽管帖子使用较旧的C/C++X语法).

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

Outer C++/WinRT Windows Runtime Component

如果我这样做,我可以添加参考就好了.

Successful Reference

但是,当我尝试构建时,我遇到了构建失败.

1>------ Build started: Project: InnerCSharp,Configuration: Debug x86 ------
1>  InnerCSharp -> C:UserslithesourcereposEntityFrameworkInsideC++InnerCSharpbinx86DebugInnerCSharp.winmd
2>------ Build started: Project: OuterC++WinRT,Configuration: Debug Win32 ------
2>MIDLRT Processing C:UserslithesourcereposEntityFrameworkInsideC++OuterC++WinRTClass.idl
2>Class.idl
2>MIDLRT Processing C:Program Files (x86)Windows Kits10Include10.0.17134.0winrtwinrtbase.idl
2>winrtbase.idl
2>MIDLRT Processing C:Program Files (x86)Windows Kits10Include10.0.17134.0winrtmidlbase.idl
2>midlbase.idl
2>Processing WinMD c:userslithesourcereposentityframeworkinsidec++innercsharpbinx86debuginnercsharp.winmd
2>Processing WinMD c:program files (x86)windows kits10references10.0.17134.0windows.ai.machinelearning.preview.machinelearningpreviewcontract1.0.0.0windows.ai.machinelearning.preview.machinelearningpreviewcontract.winmd
... snip ...
2>Processing WinMD c:program files (x86)windows kits10references10.0.17134.0windows.ui.viewmanagement.viewmanagementviewscalingcontract1.0.0.0windows.ui.viewmanagement.viewmanagementviewscalingcontract.winmd
2>MDMERGE : error MDM2006: C:UserslithesourcereposEntityFrameworkInsideC++InnerCSharpbinx86DebugInnerCSharp.winmd does not appear to be a valid Windows Runtime metadata file
2>MDMERGE : error MDM2005: Unable to open metadata file C:UserslithesourcereposEntityFrameworkInsideC++InnerCSharpbinx86DebugInnerCSharp.winmd.
2>Microsoft(R) Metadata Merge Utility Version 10.0.45.
2>
2>
2>Creating output directory C:UserslithesourcereposEntityFrameworkInsideC++DebugOuterC++WinRTMerged.
2>Load input metadata file C:UserslithesourcereposEntityFrameworkInsideC++InnerCSharpbinx86DebugInnerCSharp.winmd.
2>Load input metadata file C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract1.0.0.0Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract.winmd.
... snip ...
2>Load input metadata file C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.UI.ViewManagement.ViewManagementViewScalingContract1.0.0.0Windows.UI.ViewManagement.ViewManagementViewScalingContract.winmd.
2>Processing input metadata file C:UserslithesourcereposEntityFrameworkInsideC++DebugOuterC++WinRTUnmergedClass.winmd.
2>C:Program Files (x86)Microsoft Visual Studio2017CommunityCommon7IDEVCVCTargetsMicrosoft.Cpp.CppWinRTEnabled.targets(244,9): error MSB3073: The command "mdmerge.exe -v -metadata_dir "C:UserslithesourcereposEntityFrameworkInsideC++InnerCSharpbinx86Debug." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract1.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.ApplicationModel.Calls.CallsVoipContract3.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.ApplicationModel.SocialInfo.SocialInfoContract2.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.ApplicationModel.StartupTaskContract3.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Devices.Custom.CustomDeviceContract1.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Devices.DevicesLowLevelContract3.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Devices.Printers.PrintersContract1.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract3.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Devices.SmartCards.SmartCardEmulatorContract5.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Foundation.FoundationContract3.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Foundation.UniversalApiContract6.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Gaming.XboxLive.StorageApiContract1.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Graphics.Printing3D.Printing3DContract4.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Networking.Connectivity.WwanContract2.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Services.Store.StoreContract3.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.Services.TargetedContent.TargetedContentContract1.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.System.Profile.ProfileHardwareTokenContract1.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.System.Profile.ProfileSharedModeContract2.0.0.0." -metadata_dir "C:Program Files (x86)Windows Kits10References10.0.17134.0Windows.UI.ViewManagement.ViewManagementViewScalingContract1.0.0.0." -o "C:UserslithesourcereposEntityFrameworkInsideC++DebugOuterC++WinRTMerged" -i "C:UserslithesourcereposEntityFrameworkInsideC++DebugOuterC++WinRTUnmerged" -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中的步骤成功引用Win2D,无论是在C / WinRT Windows运行时项目中(无需任何其他配置),还是在ComponentC Windows桌面动态链接库项目中(并运行cppwinrt命令行工具)如this answer中所述.但是,这对我没有帮助 – 我不是要尝试引用NuGet包;我试图在同一个解决方案中引用一个不同的项目.

毕竟,问题是:如何使用Universal Windows Runtime从C代码调用C#代码?

解决方法

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

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

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

另一个选择是主持CLR in your process manually and invoke code that way.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读