c# - 从 TLB 程序集创建 DLL

标签 c# dll com interop

在使用 dynamic 关键字 ( more information here ) 从 C# 调用 COM TLB 方法时,我遇到了一些性能问题。因为我没有任何运气来尝试优化这样的调用,所以我现在正在寻找一种方法将我的 TLB 库转换为我可以直接在我的 C# 项目中使用的 native 包装 DLL(在这个阶段我什至不确定这是否会帮助,而是将性能问题抽象到一层)。

我已经使用 tlbimp.exe 使用 VS2013 命令提示符和命令从我的 COM .tlb 文件(已注册)创建一个 .dll

tlbimp F:\SomeDir\GrpSvr.tlb /out:F\SomeDir\GrpSvr.dll 

这生成了一个托管包装器 C# .dll,我可以使用 dotPeek 检查它。它包含预期的命名空间

namespace GRPSVR
{
    [TypeLibType(TypeLibTypeFlags.FCanCreate)]
    [Guid("FFB54BC4-B15E-11D1-99BC-0000E803C444")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComImport]
    public class GrpCallClass : IGrpCall, GrpCall { /*Expected Methods et al.*/ }
}

和两个接口(interface) IGrpCall 包含生成类的完整模板和空接口(interface) GrpCall。我使用 regasm.exe

注册了这个 .dll
regasm F:\SomeDir\GrpSvr.dll 

现在,我在我的项目中包含对此 .dll 的引用,并尝试通过

实例化 GrpCallClass
private GRPSVR.GrpCallClass grpSvr = new GRPSVR.GrpCallClass();

但这会导致编译时错误:

Interop type 'GRPSVR.GrpCallClass' cannot be embedded. Use the applicable interface instead.

那我试试

private GRPSVR.IGrpCall grpSvr = new GRPSVR.GrpCall();

这在编译时有效,但在运行时我得到一个

Additional information: Retrieving the COM class factory for component with CLSID {FFB54BC4-B15E-11D1-99BC-0000E803C444} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

但是注册了.dll。

  1. 这种方法是否有助于提高初始 COM TLB 程序集中调用方法的性能?

  2. 有人可以解释我做错了什么以及如何将我的 COM .tlb 库转换为 native 包装器 .dll 吗?

感谢您的宝贵时间。

最佳答案

I register this .dll using regasm.exe

这是一个致命的错误。这覆盖了 native COM 服务器的注册表项。仅当服务器是用 .NET 语言编写时才应使用 Regasm。您将不得不重新安装服务器以修复损坏。请务必先运行 Regasm/unregister 以清理注册表。

and empty interface GrpCall

您看到一个空接口(interface)是您必须在 C# 代码中使用 dynamic 关键字的原因。 COM 服务器的作者只允许您在后期绑定(bind)时使用它。相当于 .NET 中的 [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]。这并不少见,它避免了很多 DLL hell 的痛苦。但是可以肯定的是,后期绑定(bind)不是很快,因为在运行时需要额外的调用来查找您正在调用的方法的 dispid。设置堆栈帧以进行调用也很慢,每个参数都必须转换为 VARIANT。与早期绑定(bind)调用相比,速度降低 10 倍是很正常的,对于一个简单的属性来说可能是几个数量级。

您无法避免这种情况,您必须与服务器作者合作才能取得成功。一个漂亮的顶部奶酪是解决它的方法,要求双界面。期待一个“否”,你可能会得到一个"is"。

关于c# - 从 TLB 程序集创建 DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22711523/

相关文章:

c# - HtmlDecode 不能在 html 属性中使用 Razor MVC

dll - 为什么 mingw 编译的 Game Maker 扩展在没有 -static 的情况下编译时会在退出时崩溃?

c++ - 使用 Visual Studio 2012 Express Version 引用 dll

android - 使用 ADB shell 命令从 Android 设备读取短信

windows - 通过 PowerShell 加载类型库并编写 Windows Live Writer 脚本

c# - C#COM可见类型:是否需要GUID?

c# - 为什么 ImageResizer 总是将图像大小调整为 900 宽度?

c# - 使用 C# 和 .net 3.5 阅读 RSS 的问题

c# - Windows Phone 更新 ListView

c++ - 无法在动态链接库 libstdc++-6.dll 中找到过程入口点 __gxx_personality_v0