1

I have followed the tutorial on the following page to create a c++ DLL and I have put it in the System32 folder: http://msdn.microsoft.com/en-us/library/ms235636%28v=vs.80%29.aspx. I am able to run the .exe from anywhere on the PC. Now I want to be able to call Add from a VB.NET application, so I have added the following code:

Imports System.Runtime.InteropServices

Public Class Form1

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Try
            Dim Test As Integer
            Test = Add(1, 1)
            MsgBox(Test)
        Catch ex As Exception

        End Try
    End Sub

    <DllImport("MathFuncsDll.dll", EntryPoint:="Add", SetLastError:=True, CharSet:=CharSet.Ansi)> _
    Private Shared Function Add(ByVal a As Double, ByVal B As Double) As Double
    End Function

End Class

I get the following error: Unable to find an entry point named 'Add' in DLL 'MathFuncsDll.dll. I believe this is because of the namespace. I have researched this and some web pages say namespaces are not allowed with Platform Invoke and some web pages say they are allowed. What is the problem?

w0051977
  • 15,099
  • 32
  • 152
  • 329

2 Answers2

4

The entry point is not named "Add". From the Visual Studio Command Prompt, run dumpbin /exports MathFuncsDll.dll to see the exported names. To get this declaration:

<DllImport("MathFuncsDll.dll", EntryPoint:="?Add@MyMathFuncs@MathFuncs@@SANNN@Z", _
           CallingConvention:=CallingConvention.Cdecl)> _
Private Shared Function Add(ByVal a As Double, ByVal B As Double) As Double
End Function

The strange looking name is produced by the C++ compiler, a feature called "name decoration". It supports function overloading. You can put extern "C" in front of the function declaration to suppress it. It is actually better if you don't. Also note that SetLastError wasn't correct, the code doesn't actually call SetLastError() to report errors. And CharSet wasn't appropriate, these functions don't take strings.

You'll also need to do something about the Divide function, throwing a C++ exception won't come to a good end in an interop scenario, only C++ code can catch the exception.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks. +1 for the reference to dumpbin.exe. I have done what you suggested and now the error is: "WindowsApplication1.Form1::Add' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke" – w0051977 Oct 14 '12 at 18:43
  • Almost there, the calling convention isn't __stdcall. Post corrected. – Hans Passant Oct 14 '12 at 19:04
0

Namespaces are not allowed. PInvoke works like plain C client. Don't forget also to declare MathFuncsDll as extern "C" to prevent C++ name mangling. Use Dependency Walker or dumpbin to see list of functions exported from MathFuncsDll.

Alex F
  • 42,307
  • 41
  • 144
  • 212
  • Thanks for answering but please see Hans Passant's answer. It appears that it is possible to use namespaces. – w0051977 Oct 14 '12 at 19:11
  • Of course, if you use decorated names in PInvoke declaration. Classic way is to use extern "C", this just looks better. Decorated names are used in PInvoke mostly when we need to use third-party library without source code, which exports C++ functions. – Alex F Oct 14 '12 at 19:24