【问题标题】:Exposing an ISO C++ class to a VB6 application向 VB6 应用程序公开 ISO C++ 类
【发布时间】:2011-05-31 03:15:20
【问题描述】:

我开发了一个 C++ 类来访问 USB 上的软件保护加密狗。 C++类在Linux下是用g++开发的,但是我在Windows下用MinGW可以编译成功。我有一个使用 VB6 (Visual Basic 6) 构建的科学应用程序。

问题是如何将我的 C++ 类公开给 VB6 应用程序?有哪些可能的方法来做到这一点?我需要使用 COM 吗? (嗯,“无微软”的解决方案更可取:)

非常感谢您的帮助!

更新 1. 阅读您的 cmets 我意识到我需要为 C++ 类实现一个 COM 包装器。周围有什么好的和最近的例子吗?我可以使用 MinGW(并避免 MSVC)实现 COM 包装器吗?

更新 2。 最后,我决定为这个问题提供悬赏。以下是我想更好地理解的事情:

1. 我意识到我需要为我的 C++ 类实现一个 COM 包装器。有人可以为我提供如何为这样的课程制作这个的工作示例:

class ValueMapper
{
public:
    ValueMapper( ) { }

    ValueMapper( double fmin, double fmax, int ilength ) {
        SetMapping( fmin, fmax, ilength );
    }

    inline double GetMin() { return min; }
    inline double GetMax() { return max; }
    inline int GetLength() { return length; }

    virtual inline void SetMapping( double fmin, double fmax, int ilength )
    {
        min = fmin;
        max = fmax;
        length = ilength;
    }

    virtual inline int MapValue( double value ) {
        double factor = length / (max - min);
        return (int)RoundTo( (value-min) * factor );
    }

    static double RoundTo( double value, double eps = 1 ) {
        return floor(value/eps + 0.5) * eps;
    }

protected:
    double  min;
    double  max;
    int     length;
};

2. 如何使用 VB6 生成的 COM 包装器?我需要注册一个COM服务器吗?不注册可以使用吗?

3. 可选。是否可以使用 MinGW 实现 COM 包装器?

【问题讨论】:

  • 您为什么要避免使用 COM? VB 6 在 COM 开发中完全根深蒂固。很难想象您在尝试使用“无 Microsoft”解决方案时会取得什么成就。如果您愿意,您就不会编写 VB 6 应用程序或在 Windows 上运行它。
  • @Cody Gray,感谢您提供指向笔记的链接!真的很值得一读。好吧,看来我需要使用COM。最近有没有 ISO C++ 类的 COM 包装器示例?
  • 你没有使用 COM。还有其他方法可以做到这一点,但通过 COM 做到这一点实际上更简单。这有点讽刺,因为从历史上看,COM 没有什么“简单”的东西,但这就是 VB 6 的基础,一旦您克服了 COM 开发的最初障碍,它确实大大简化了这样的互操作场景。我真的不能给你任何关于 MinGW 的建议。我不太关心它,也从未真正将它用于严肃的 Windows 开发。

标签: c++ class com vb6


【解决方案1】:

要从 Visual Basic 访问 COM C++ 类,您需要使用称为 IDL 的元语言指定其接口。它将用于生成将由 Visual Basic 读取的类型库和 C++ 中的类骨架,以像委托对 ValueMapper 对象的调用一样实现。它由名为 midl.exe 的工具完成。它带有 Windows 平台 SDK 或任何 VC++ 环境。如果您没有,您可以免费下载它和 VC++ 10 Express Edition。

对象的 IDL 文件可能如下所示:

import "oaidl.idl"; 
[
 uuid(C6907FD4-9F56-499A-A784-6168AB3352D6),
 version(1.0),
 local,
 oleautomation
]
interface IValueMapper : IDispatch
{
  [id(1), propget] double Min();
  [id(2),propget] double Max();
  [id(3),propget] int Length();
  [id(4)] void SetMapping( [in] double fmin, [in] double fmax, [in] int ilength );
  [id(5)] int MapValue([in] double value);
  [id(6)] double RoundTo( [in] double value,[in,defaultvalue(1)] double eps );
};

[
  uuid(1C110E43-A56F-41A2-8052-EF85FF96082F),
  version(1.0),
  helpstring("Value Mapper Library"),
] library ValueMapperLib
{
  importlib("stdole32.tlb");
  interface IValueMapper;
  [
  uuid(D1A2F830-994E-4495-A9C3-1440155578A9),
  helpstring("Value Mapper Component Class")
  ] 
  coclass ValueMapperClassObject
  {
    [default] interface IValueMapper;
  }; //end coclass def
};

现在,您可以通过从 IValueMapper 派生类来提供所需的功能,并使用 ValueMapper 成员实现其功能。不幸的是,您还需要提供一些样板代码来实现类对象、IUnknown 和 IDispatch 接口以及 DLL 注册代码。您可以在 Internet 上找到相关代码 sn-ps,即在以下页面上:

http://www.dcl.hpi.uni-potsdam.de/LV/Components04/VL5/MSDN/DrGUI-on-COM.html http://www.codeproject.com/KB/COM/simplecomserver.aspx

我还组装了一个实现此接口的 VC++ 10 完整项目,如果您想看看,请告诉我。

【讨论】:

  • 感谢您的回答!有没有办法从 C++ 类头文件中制作 IDL 文件?我是否总是需要提供 .tlb 文件才能在 VB6 项目中使用生成的 COM 对象 DLL?
  • 由于 IDL 包含比类头更多的信息,如标记 in、out 参数,因此通常不可能从标准类头生成它。 VB 需要 .tlb 库来了解类接口,但它由 midl 编译器自动生成并由 VB 读取。所以你不必担心。
  • 好的,我想我明白了。所以我需要 (1) 创建一个带有接口描述的 IDL 文件,(2) 使用 midl.exe 实用程序生成一个 C++ 头文件,(3) 实现相应的 COM 对象,(4) 将其编译成一个 DLL 文件,( 5) 从 IDL 中生成一个 .tlb 文件以在 VB6 应用程序中使用我的 COM 对象,(6) 将 .tlb 导入到 VB6 项目中。对吗?
  • 另外两个问题:有没有支持 IDL 编程的免费编辑器(或者可能只是 IDL 语法高亮)?是否可以在 IDL 中指定自定义类型(结构)的数组作为输入/输出参数并在 VB6 中使用?
  • 是的,为方便起见,您可以使用 VC++ 项目中的资源文件 (.rc) 将 .tlb 库放入 dll 中,并同时注册两者。查看我发布的第二个链接,它附带了一个示例项目,其中包含一些可以重用的通用代码。
【解决方案2】:

我知道有两种可能的方式:

1) 为您的类编写一个 COM 包装器并直接从 VB6 访问它。

2) 为您的类创建一个 C 接口(通过“扁平化”)并将其公开在一个普通的 DLL 中。

前一种方法更常见,但听起来您可能更喜欢后者。

【讨论】:

  • 感谢您的回答。我觉得写一个 COM 包装器会不会那么痛苦?!
  • @ezpresso:这真的取决于你更喜欢什么。事实上,如果你使用的是 MingW,编写一个 COM 组件可能一点都不简单。
猜你喜欢
  • 2011-02-05
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-16
  • 1970-01-01
相关资源
最近更新 更多