簡體   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