Search code examples
c++wpfvb.netdllexport

How to call C++ DLL function from VB?


I need to call a function from C++ Dll (BVRelate.dll) through Visual Basic (VBWpf).

C++ dll code:

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

Then I try to call this function from VB (wpf project)

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

And I got an exception:

"MarshalDirectiveException was unhandled". An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in VBWpf.exe

Then I used dumpbin:

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

and in VBRelate.txt was this:

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

Then I was trying to use def file, but not really fully understand how to use it (where should it be - with dll file, with project files or somewhere else) and why should I use it while using __declspec (not __stdcall). So I put the def file in the directory with dll file, and also with dll projects files:

; VBRelate.def - defines the exports for VBRelate.dll

LIBRARY VBRelate.dll
DESCRIPTION 'A C++ dll that can be called from VB'

EXPORTS
    DoSomething

Then I rebuilt dll. It didn't work. The same exception appeared. And dumpbin returned the same dump, nothing was changed.


Solution

  • SOLVED

    Adding extern "C" in dll function declaration and definition made it work.

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

    so as I think the problem was in decorated name. After adding extern "C" the dump file looked like this:

    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
    

    So the function name now is right, but it was ?DoSomething@@YAXXZ