How to call a C++ DLL from VB6 without going through COM?

﹥>﹥吖頭↗ 提交于 2021-02-19 08:48:28

问题


OK, so I have a C++ project that compiles to a DLL file. I am able to reference this file in C# and see/use all of the objects and functions within the DLL file. What I need to do is to reference those objects and function through VB6.

The C++ code has nothing in it that looks like it's creating a DLL. There are no '__declspec(dllexport)' modifiers, just C++ code.

There are objects like this:

String ^
Array^

I'm not entirely sure what they are. My knowledge of C++ is not very extensive and I've only coded in C++ for Linux systems, although from the usage they sort of look like pointers. Do these objects have anything to do with a DLL in C++?

Anyway, I can add any wrappers that I need or add a definition file (.def), although I do not know what wrappers to use and I don't know how a definition file works or how it needs to be constructed.

Any help and/or suggestions are appreciated. If you can refer me to some good info as well, that would be helpful. All searching I have done has not helped.

Remember, I need to access all functions and objects in this C++ DLL from VB6.

Thanks.

EDIT: Added .h file and AssemblyInfo.cpp spec to the question

I changed some names in these files, but the structure is the same. Note that this references other files, but I assume that if one can be made to work then the others can with the same process. I can see every object, just not the methods:

//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;

};
}

Here is the AssemblyInfo.cpp file:

#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:


Use regasm to create a COM Type Library (.TLB) file from your C++/CLI assembly.

You should now be able to reference the C++/CLI code by referencing the TLB file in your VB6 code. From the example there:

In its simplest form, you can do:

REGASM MyAssembly.dll

Now, all of the COM-compatible classes are registered as COM objects. You can fire up VB6 and start writing code:

Dim net As Object

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

Pretty easy. Except that you're late binding because you don't have a COM type library.

No problem! REGASM can generate a type library for you and even register it:

REGASM MyAssembly.dll /tlb:MyAssembly.tlb

Now, in VB6 you can add a reference to the type library and use early binding:

Dim net As Foo

Set obj = New NETProject.Foo
obj.Move

EDIT: Make the class COM visible like this:

[ComVisible(true)]
public ref class MyDataBaseAccessor



回答2:


I'm not entirely sure what they are.

You are not looking at C++ code, but at C++/CLI code, a language targeting the managed .NET platform. This is also why you can easily use this DLL in C#.

Honestly, if you want to use managed objects in Visual Basic 6, COM Interop is your best bet. Either create a wrapper or directly expose the objects contained in the DLL via COM Interop.

Edit:

Basically, you expose objects by using attributes, i.e. you annotate your types in source code with attributes. Those are documented here: System.Runtime.InteropServices

Have a look at: Introduction to COM Interop

Also, the COM Interop "bible" is this book by Adam Nathan: .NET and COM: The Complete Interoperability Guide

There is also an article dealing with how to expose a COM object and use it in VB6: http://www.15seconds.com/issue/040721.htm



来源:https://stackoverflow.com/questions/3843350/how-to-call-a-c-dll-from-vb6-without-going-through-com

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!