2016-09-22 110 views
0

我需要通过Visual Basic(VBWpf)从C++ Dll(BVRelate.dll)调用函数。如何从VB调用C++ 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 [email protected]@YAXXZ = @ILT+660([email protected]@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返回了相同的转储,没有任何更改。

+1

计划与选项严格了一会儿所以编译器?可以告诉你这样一个简单的错误。它是一个子,而不是一个功能。 –

+0

我开启了这个选项,thanx。我试着声明函数DoSomething Lib“M:\ VBRelate.dll”()作为对象,并声明Sub DoSomething Lib“M:\ VBRelate.dll”()。同样的问题 –

+0

在dll函数声明和定义中添加extern“C”使它工作。 –

回答

0

该问题似乎不在DLL /本机C++代码中,但是如果您将其作为托管C++ dll?唯一的例外是说有什么问题管理(VB)之间处理数据和非托管(C++)代码:MarshalDirectiveException on MSDN

它可能会使用MarshalAsAttribute()msdn

+0

不要低头......我应该编组哪些属性?该函数是无效类型,并没有参数... void DoSomething() –

+0

也许有函数名称有问题吗?当我读它应该不是这样吗?DoSomething @@ YAXXZ = @ ILT + 660(?DoSomething @@ YAXXZ)在转储 –

+1

在dll函数声明和定义中添加extern“C”使它工作。 –

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); 
    } 
} 

所以我认为问题是在装饰名称。添加外部的“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