1

I am new to using PInvoke with Classic C++ and I asked this question yesterday: Using Windows API functions in .NET

I have now created a very simple C++ program as follows:

#include <iostream>
#include <stdio.h>
#include <string>
extern "C" __declspec(dllexport) int hello()
{
  //printf ("Hello World!\n");
  return 1;
} 

I then compiled the DLL using the following command: g++ -c mydll.cpp Then created the shared library using the following command: g++ -shared -o mydll.dll mydll.o, then copied mydll.dll to C:\Windows\syswow64.

I then created a new VB.NET project and created the following code:

    Imports System.Runtime.InteropServices
Public Class TestPlatformInvoke
    <DllImport("mydll.dll", CallingConvention:=CallingConvention.Cdecl)> _
    Public Shared Function hello() As Integer
    End Function
    Public Sub New()
        Try
            Dim test As Integer = hello() 'Line 6 ex As Exception
            'I don't swallow exceptions
            MsgBox("test")
        Catch ex As Exception

        End Try
    End Sub
End Class

The application exits after calling hello(). It does not throw an exception.

I am trying to get to grips with how this works. I don't have any commercial experience with c++; only academic experience at university.

Here is an image of Dependancy Walker for mydll.dll.

enter image description here

Community
  • 1
  • 1
w0051977
  • 15,099
  • 32
  • 152
  • 329

2 Answers2

2

If you use Visual Studio to debug programs and include the DLL in your project (Visual Studio 2012 Express Edition allows including projects of different types in the solution), you may set the "Allow native code debugging" option to automatically switch the debugger from the VB.NET to C++, when you P/Invoke function from the DLL.

Here's a working Proof-of-concept. Simply unzip, open in Visual Studio, build and run. You may compare this program with your project and find the differences, which makes your code failing.

I guess, that you haven't actually exported the function from the DLL. Simply including it in the DLL's code may not be enough: check, which functions are exported from the DLL using the Dependency Walker (other link) program. For example, I had to add folowing declaration:

__declspec(dllexport) int __stdcall Test() { ... }

And additionally create the .def file for the names for exported functions not to be decorated.

Try to modify your DLL source code and change the function declaration to:

extern "C" __declspec(dllexport) int hello()
{
  return 1;
}  
Spook
  • 25,318
  • 18
  • 90
  • 167
  • Thanks. I am not the downvoter. I have added a messagebox after the call to the hello function (see line 7). This message box is not reached. – w0051977 Mar 01 '13 at 11:10
  • The link you have provided is to a zip file that does not exist. – w0051977 Mar 01 '13 at 11:14
  • @w0051977 I've made a mistake in the link, it's fixed now. – Spook Mar 01 '13 at 11:19
  • Did you register the C++ DLL? in the example link. – w0051977 Mar 01 '13 at 11:26
  • What do you mean by registering the C++ DLL? – Spook Mar 01 '13 at 11:28
  • I cannot find a DLL in the project folder. – w0051977 Mar 01 '13 at 11:29
  • 2
    Avoid decoration by using cdecl. Avoid mangling by using extern "C". And then you can skip the .def file. – David Heffernan Mar 01 '13 at 11:30
  • Its source code is in the Library folder. Do you open the solution with Visual Studio (PInvokePoC.sln)? If so, simply rebuild the whole solution and the DLL will appear. Otherwise you have to figure out how to compile it, I have no knowledge about other compilers. For your convenience, I've compiled the project for you, you can get binaries here: http://spook.freshsite.pl/Temporary/LibraryPoC-Binaries.zip – Spook Mar 01 '13 at 11:30
  • @SysDragon The answer looked different when it was downvoted. The section about the function not being imported was added later. Not that I was the downvoter, but the downvotes were appropriate at the time I feel. – David Heffernan Mar 01 '13 at 11:41
  • I have edited my question with where I am up to. Can you take another look? – w0051977 Mar 01 '13 at 19:03
2

Declare is VB6 legacy. You should use p/invoke and the DllImport attribute.

<DllImport("mydll.dll", CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Function hello() As Integer
End Function

There are lots of ways that this could fail. Perhaps the DLL is not loading because there's a 32/64 bit mismatch. Also, your calling conventions do not match. Your DLL will be using cdecl but your VB code uses stdcall. The pinvoke above fixes that.

Most seriously your function does not appear to have been exported from the DLL. That's going to make it fail for sure. Use Dependency Walker to determined whether or not your function has been exported. I'm not so familiar with g++ so you'll have to work out how to export your function using the GNU toolchain. But watch out for name decoration and name mangling. You may need to take care with how you export your function so that it is exported with the desired name.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks for your help so far. +1. I have edited the question with the code as it stands after your advice. Could you take a look? The same problem stands. I have a 64 bit windows machine and I am running Visual Web Developer as I am working on my home machine. – w0051977 Mar 01 '13 at 18:48
  • I am almost ready to mark this question as answered. Are you able to answer the question in my last comment? – w0051977 Mar 01 '13 at 21:45
  • Two comments. 1. Is your calling process the same bitness as the DLL? Is your DLL 32 bit? And is your VB process also 32 bit? 2. Don't put the DLL in the system directory. That's private, don't write there. Put the DLL in the same directory as the VB exe file. – David Heffernan Mar 01 '13 at 22:44
  • Thanks again for your help. I think the problem could be that I am using Cygwin to compile the c++. I am going to try using visual studio c++ tomorrow. Do you think this could be the problem? – w0051977 Mar 01 '13 at 22:54
  • Very plausible. Must be something like that. The code in the Q is now fine. If you want to use GNU compiler on Windows go for mingw. – David Heffernan Mar 01 '13 at 22:59
  • The solution was to compile the C++ DLL using Visual C++ as stated in my last question. I have asked another question about this here in case you wanted to take a look: http://stackoverflow.com/questions/15173692/use-c-dll-in-net. – w0051977 Mar 02 '13 at 11:01