如何从VB调用C ++ DLL函数?

时间:2016-09-22 13:58:34

标签: c++ wpf vb.net dllexport

我需要通过Visual Basic(VBWpf)从C ++ Dll(BVRelate.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未处理”。 VBWpf.exe中发生未处理的“System.Runtime.InteropServices.MarshalDirectiveException”类型异常

然后我用了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返回了相同的转储,没有任何改变。

2 个答案:

答案 0 :(得分:0)

问题似乎不在DLL /本机C ++代码中,尽管可能是因为您将其设置为托管C ++ DLL?例外情况是在托管(VB)和非托管(C ++)代码之间处理数据有问题:MarshalDirectiveException on MSDN

可以使用MarshalAsAttribute() msdn

更改属性

答案 1 :(得分:0)

<强>解决

在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

所以函数名称现在是正确的,但它是?DoSomething @@ YAXXZ