如何在VB中调用c++ DLL函数

How to call C++ DLL function from VB?

本文关键字:c++ DLL 函数 调用 VB      更新时间:2023-10-16

我需要通过Visual Basic (VBWpf)从c++ Dll (bvrelation . Dll)调用函数。

c++ dll代码:
//VBRelate.h
#ifdef VBRELATE_EXPORTS
#define VBRELATE_API __declspec(dllexport)
#else
#define VBRELATE_API __declspec(dllimport)
#endif
extern VBRELATE_API void DoSomething();
//VBRelate.cpp
#include <atlstr.h>
#include "VBRelate.h"
VBRELATE_API void DoSomething()
{
    CString strOutput("Hello world");
    MessageBox(NULL, strOutput, L"Got a message", MB_OK);
}

然后我尝试从VB (wpf项目)调用这个函数

Imports System.Runtime.InteropServices
Class MainWindow
    Declare Function DoSomething Lib "M:VBRelate.dll" ()
    Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
        DoSomething()
    End Sub
End Class

我得到了一个异常:

"MarshalDirectiveException未处理"。类型为"System.Runtime.InteropServices"的未处理异常。MarshalDirectiveException'发生在VBWpf.exe

然后我使用dumpbin:

dumpbin /exports "M:VBRelate.dll">M:VBRelate.txt

和在VBRelate.txt中是这样的:

Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file M:VBRelate.dll
File Type: DLL
  Section contains the following exports for VBRelate.dll
    00000000 characteristics
    57E3DDA6 time date stamp Thu Sep 22 16:33:26 2016
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names
    ordinal hint RVA      name
          1    0 00011299 ?DoSomething@@YAXXZ = @ILT+660(?DoSomething@@YAXXZ)
  Summary
        1000 .00cfg
        4000 .data
        1000 .gfids
        1000 .idata
        4000 .rdata
        1000 .reloc
        1000 .rsrc
       10000 .text
       10000 .textbss
        1000 .tls

然后我试图使用def文件,但不是真正完全理解如何使用它(它应该在哪里-与dll文件,与项目文件或其他地方),为什么我应该使用它,而使用__declspec(不是__stdcall)。所以我把def文件放在dll文件目录下,还有dll项目文件:

; VBRelate.def - defines the exports for VBRelate.dll
LIBRARY VBRelate.dll
DESCRIPTION 'A C++ dll that can be called from VB'
EXPORTS
    DoSomething

然后我重建dll。但没有成功。同样的例外出现了。dumpbin返回相同的转储,没有任何改变。

问题似乎不在DLL/本机c++代码内,尽管也许如果您使其成为托管c++ DLL ?例外是说有一些错误的处理托管(VB)和非托管(c++)代码之间的数据:MSDN上的MarshalDirectiveException

可以使用MarshalAsAttribute() msdn

更改属性

SOLVED

在dll函数的声明和定义中加入extern "C"使其正常工作。

 //VBRelate.h
 #ifdef VBRELATE_EXPORTS
 #define VBRELATE_API __declspec(dllexport)
 #else
 #define VBRELATE_API __declspec(dllimport)
 #endif
extern "C" VBRELATE_API void DoSomething();
//VBRelate.cpp
extern "C"
{
    VBRELATE_API void DoSomething()
    {
        CString strOutput("Hello world");
        MessageBox(NULL, strOutput, L"Got a message", MB_OK);
    }
}

所以我认为问题出在名字上。在添加extern "C"之后,转储文件看起来像这样:

Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file M:VBRelate.dll
File Type: DLL
  Section contains the following exports for VBRelate.dll
    00000000 characteristics
    57E52794 time date stamp Fri Sep 23 16:01:08 2016
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names
    ordinal hint RVA      name
          1    0 000112C1 DoSomething = @ILT+700(_DoSomething)
  Summary
        1000 .00cfg
        4000 .data
        1000 .gfids
        1000 .idata
        4000 .rdata
        1000 .reloc
        1000 .rsrc
       10000 .text
       10000 .textbss
        1000 .tls

所以函数名现在是正确的,但它是?