我需要通过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
所以函数名现在是正确的,但它是?