繁体   English   中英

从VB6调用C dll,该dll是使用Visual Studio 2013编写的

[英]Calling C dll from VB6, where the dll is written using Visual Studio 2013

这个问题的位置很差,但是我正在忙着大转弯,我不确定如何更好地表达它。

我需要使用C编写一个DLL,将从VB6调用它。 我正在使用Visual Studio Express2013。我知道... VB6很古老,我认为代码管理人员现在确信他们应该将其当作垃圾。 但是与此同时,这需要完成。

首先,我试图用一个函数编写一个DLL,该函数除了打印一条消息外什么也不做,并且在使用VB.NET调用DLL时工作正常。

这就是TinyDll.h的内容。

#ifdef TINYDLL_EXPORTS
#define TINYDLL_API __declspec(dllexport)
#else
#define TINYDLL_API __declspec(dllimport)
#endif

extern TINYDLL_API void __stdcall testdll();

这是TinyDll.cpp

#include "stdafx.h"
#include "TinyDll.h"
#include <stdexcept>

using namespace std;

void __stdcall testdll()
{
  printf("Got into the dll.\n");
}

顺便说一句,无论是否使用__stdcall,我都尝试过。 我还尝试使用.def文件对dll中的名称进行分解,但现在尚不清楚它是否可以正常工作。 我发现的示例表明这应该可行

LIBRARY TinyDll
Exports
  testdll

但事实并非如此。 dll中的名称仍然是乱码形式:?testdll @@ YGXXZ。

我的测试代码相当琐碎,并且可以与VB.NET完美配合,但不适用于VB6。 该问题与VB6进程无法找到dll和/或在其中查找功能有关。 作为记录,这是用于测试的VB6代码

Declare Sub testdll Lib "TinyDll.dll" Alias "?testdll@@YGXXZ" ()

Sub Main()
  testdll()
End Sub    

首先,我是否正确,没有必要调用regsvr32或regasm? dll不是COM对象-VB6正在调用我的C代码,而不是相反。 当我们尝试执行这两项操作时,“找不到入口点DllRegisterServer”或“找不到指定的模块”。

最重要的是,VB6开发环境太旧了,无法在我的Windows 7计算机上运行,​​并且试图测试我的DLL的人处于另一种状态,并且严格来说是VB程序员。

我已经阅读了通过谷歌搜索所能找到的所有内容,所以我希望有人知道一个网站清楚地列出了事实或显示了有效的示例。

这种问题(例如,涉及一个粗糙的旧环境被用来做它本来没打算做的事情)的情况经常如此,它现在可以工作,但不清楚为什么。

我们认为,如果没有dll的完整路径,VB6找不到它。 如果我们用

Declare Function TestTinyDLL Lib "e:\full\path\down\to\TinyDll.dll" Alias "_testdll@0"

然后调用就可以了,但是如果没有给出完整路径,则无论dll位于何处都不会起作用。 我们还发现,可以通过如下所示“初始化” dll来避免提供完整路径(这是由于:出于此提示, 从vb6加载dll时找不到文件 ):

Option Explicit

' Windows API method declarations
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias _
    "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, _
    ByVal msg As Any, ByVal wParam As Any, ByVal lParam As Any) _
    As Long
Private Declare Function FormatMessage Lib "kernel32" Alias _
    "FormatMessageA" (ByVal dwFlags As Long, lpSource As Long, _
    ByVal dwMessageId As Long, ByVal dwLanguageId As Long, _
    ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Any) _
    As Long

Declare Function BogusCall Lib "otherdll.dll" Alias "_BogusCall@0" () As Integer

Declare Function TestTinyDLL Lib "TinyDLL.dll" Alias "_testdll@0" () As Integer

Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000


Sub Main()

    InitializeDLL App.Path & "\" & "otherdll.dll", "_BogusCall@0"

    InitializeDLL App.Path & "\" & "TinyDLL.dll", "_testdll@0"

    Dim Version As String

    Version = "TinyDLLTestProgram" & vbCrLf & vbCrLf

    Version = Version & "BogusCall = " & CStr(BogusCall ()) & vbCrLf

    Version = Version & "TestTinyDLL= " & CStr(TestTinyDLL()) & vbCrLf

    Form1.txtOutput.Text = CStr(Version)

End Sub

Sub InitializeDLL(myDLL As String, myFunc As String)

    ' Locate and load the DLL. This will run the DllMain method, if present
    Dim dllHandle As Long
    dllHandle = LoadLibrary(myDLL)

    If dllHandle = 0 Then
        MsgBox "Error loading DLL" & vbCrLf & ErrorText(Err.LastDllError)
        Exit Sub
    End If

    ' Find the procedure you want to call
    Dim procAddress As Long
    procAddress = GetProcAddress(dllHandle, myFunc)

    If procAddress = 0 Then
        MsgBox "Error getting procedure address" & vbCrLf & ErrorText(Err.LastDllError)
        Exit Sub
    End If

    ' Finally, call the procedure
    CallWindowProc procAddress, 0&, "Dummy message", ByVal 0&, ByVal 0&

End Sub

' Gets the error message for a Windows error code
Private Function ErrorText(errorCode As Long) As String

    Dim errorMessage As String
    Dim result As Long

    errorMessage = Space$(256)
    result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0&, errorCode, 0&, errorMessage, Len(errorMessage), 0&)

    If result > 0 Then
        ErrorText = Left$(errorMessage, result)
    Else
        ErrorText = "Unknown error"
    End If

End Function

为何有效,这是一个谜,但确实如此。 我希望这可以帮助其他面对旧VB6代码的人!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM