如何在不通过 COM 的情况下从 VB6 调用 C++ DLL?

Posted

技术标签:

【中文标题】如何在不通过 COM 的情况下从 VB6 调用 C++ DLL?【英文标题】:How to call a C++ DLL from VB6 without going through COM? 【发布时间】:2010-10-01 22:07:21 【问题描述】:

好的,所以我有一个编译为 DLL 文件的 C++ 项目。我可以在 C# 中引用此文件并查看/使用 DLL 文件中的所有对象和函数。我需要做的是通过VB6引用这些对象和函数。

C++ 代码中没有任何内容,看起来像是在创建 DLL。没有 '__declspec(dllexport)' 修饰符,只有 C++ 代码。

有这样的对象:

String ^
Array^

我不完全确定它们是什么。我对 C++ 的了解不是很广泛,而且我只为 Linux 系统编写过 C++ 代码,尽管从用法来看它们有点像指针。这些对象与 C++ 中的 DLL 有什么关系吗?

无论如何,我可以添加我需要的任何包装器或添加定义文件 (.def),尽管我不知道要使用什么包装器,也不知道定义文件如何工作或需要如何构造.

感谢任何帮助和/或建议。如果您也可以向我推荐一些好的信息,那将很有帮助。我所做的所有搜索都没有帮助。

请记住,我需要从 VB6 访问此 C++ DLL 中的所有函数和对象。

谢谢。

编辑:在问题中添加了 .h 文件和 AssemblyInfo.cpp 规范

我更改了这些文件中的一些名称,但结构相同。请注意,这引用了其他文件,但我假设如果可以使一个文件工作,那么其他文件可以使用相同的过程。我可以看到每个对象,但看不到方法:

//myDBObject.h
#pragma once
using namespace System;
namespace myDBNamespace 

#include "ProblemSolution.h"

public ref class MyDataBaseAccessor

public:
    MyDataBaseAccessor();

    static  String ^    GetServiceVersion()  return sDLLVersion;;
    int                   GetServiceStatus()  return myiDBStatus;;
    String ^                GetMyVersion();
    String ^                GetDBVersion();
    String ^                GetDLLVersion();
    String ^                GetExpireDate();

    MyOtherObject ^         GetMyOtherObject();

    int             ProcessProblem(ProblemSolution ^ dsps);

private:
    static  MyDataBaseController ^  myDataBase;
    static  MyOtherObject ^         myObjs;
    static  MyDataset ^     myDS;
    static  String ^                myDBPath;

    static  String ^                sDLLVersion = "0.01";
    static  String ^                sReqDBVer = "0.01";
    static  int                     myiDBStatus;
    static  bool                    myBoolean, myOtherBoolean, mybNoChain;

;

这是 AssemblyInfo.cpp 文件:

#include "stdafx.h"

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;

//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("My Product Title")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("My Company")];
[assembly:AssemblyProductAttribute("My Product Name")];
[assembly:AssemblyCopyrightAttribute("My Copyright")];
[assembly:AssemblyTrademarkAttribute("My Program")];
[assembly:AssemblyCultureAttribute("")];

//
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:

[assembly:AssemblyVersionAttribute("1.0.*")];

[assembly:ComVisible(true)]; //Here is the ComVisible tag. It was false and I set it to true

[assembly:CLSCompliantAttribute(true)];

[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = false)];

【问题讨论】:

【参考方案1】:

我不完全确定它们是什么。

您查看的不是 C++ 代码,而是 C++/CLI 代码,这是一种针对托管 .NET 平台的语言。这也是您可以在 C# 中轻松使用此 DLL 的原因。

老实说,如果您想在 Visual Basic 6 中使用托管对象,COM Interop 是您的最佳选择。要么创建一个包装器,要么直接通过 COM 互操作公开 DLL 中包含的对象。

编辑:

基本上,您通过使用属性来公开对象,即您在源代码中使用属性注释您的类型。这些记录在这里:System.Runtime.InteropServices

看看: Introduction to COM Interop

此外,COM 互操作“圣经”是 Adam Nathan 的这本书:.NET and COM: The Complete Interoperability Guide

还有一篇文章讨论如何在VB6中暴露一个COM对象并使用它:http://www.15seconds.com/issue/040721.htm

【讨论】:

好的,我该怎么做?在这方面完全一无所知,因为我以前从未做过 COM 互操作编程,更不用说在 C++ 中了。如何包装对象/函数?如何通过互操作公开 DLL?【参考方案2】:

使用regasm 从您的 C++/CLI 程序集中创建一个 COM 类型库 (.TLB) 文件。

您现在应该能够通过在 VB6 代码中引用 TLB 文件来引用 C++/CLI 代码。从那里的例子:

以最简单的形式,您可以这样做:

REGASM MyAssembly.dll

现在,所有 注册了 COM 兼容的类 作为 COM 对象。你可以启动VB6 并开始编写代码:

Dim net As Object

Set obj = CreateObject("NETProject.Foo")
obj.Move

很简单。除了你迟到了 绑定,因为您没有 COM 类型库。

没问题! REGASM 可以生成一个类型 图书馆为您甚至注册它:

REGASM MyAssembly.dll /tlb:MyAssembly.tlb

现在,在 VB6 中,您可以添加对 类型库并尽早使用 绑定:

Dim net As Foo

Set obj = New NETProject.Foo
obj.Move

编辑: 像这样使 COM 类可见:

[ComVisible(true)]
public ref class MyDataBaseAccessor

【讨论】:

试过了。我能够引用它,但我看不到任何对象或方法。 @Mike - 您应该能够在 OLEVIEW.EXE 中查看 TLB 文件 - 您看到要访问的内容了吗? @Steve - 在 oleview 中,TLB 文件为空,除了 UUID、版本等。声明 'library MyObject ' 为空。 @Mike - 需要将 C++/CLI DLL 中的代码标记为 ComVisible 才能使这种 VB6 集成方法起作用。你能证实吗? msdn.microsoft.com/en-us/library/ms182157(v=VS.100).aspx @Steve - 希望我早知道事情就是这么简单。大声笑找到行'[assembly:ComVisible(false)];'在 AssemblyInfo.cpp 文件中。将其更改为“true”,我现在可以看到所有内容。感谢您的帮助。

以上是关于如何在不通过 COM 的情况下从 VB6 调用 C++ DLL?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C++/CLI 调用 VB6 COM

如何在不使用表单的情况下从 jsp 调用 servlet

如何在不传递委托的情况下从 RootViewController 调用 AppDelegate 方法?

如何在不为每个帖子调用评论对象的情况下从墙上的帖子中获取评论计数?

目标 C:如何在不损失边缘质量的情况下从 JPG 图像中去除白色背景

如何在不重写的情况下从数据框中删除行?