I am trying to learn about marshaling structures and DLL's. I'm following this example.

The code builds and compiles just fine. But when I run it, the lines where the call to the function is returned; it makes the call to the function from the DLL, goes through it, but when it returns the result to the main program, it throws this exception:

A call to PInvoke function **** 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 signature match the target unmanaged signature.

I read about the problem and it says I have to verify that the calling conventions I am using are the same. Well, I'm not using any so what's the deal?

The thing is, if I hit "Continue", the code executes fine until the next function return (the first time it's for GetDistance and the second time is for InitLocation). So I don't get it.

The code works, but I want to resolve this annoying exception

I read about the problem and it says I have to verify that the calling conventions I am using are the same. Well, I'm not using any so what's the deal?

The unmanaged DLL is using a calling convention, though. To get it right, you need to know how the DLL was compiled--for example, DLLs written in C typically use the "cdecl" calling convention.

What do you know about the DLL you're using?

The thing is, if I hit "Continue", the code executes fine until the next function return (the first time it's for GetDistance and the second time is for InitLocation). So I don't get it.

That's expected; any unmanaged call that doesn't use the right calling convention will do this. Apart from the exceptions, things might be working for you now, but it could cause mysterious bugs to show up later.

Well, I think I know enough about the DLL I am using, since I created it. I created a MS C++ Project in my solution and selected DLL during the wizard. I then added a C++ item with the following code:

// TraditionalDll3.cpp
// compile with: /LD /EHsc
#include <iostream>
#include <stdio.h>
#include <math.h>

#define TRADITIONALDLL_EXPORTS
#ifdef TRADITIONALDLL_EXPORTS
   #define TRADITIONALDLL_API __declspec(dllexport)
#else
   #define TRADITIONALDLL_API __declspec(dllimport)
#endif

#pragma pack(push, 8)
struct Location {
   int x;
   int y;
};
#pragma pack(pop)

extern "C" {
   TRADITIONALDLL_API double GetDistance(Location, Location);
   TRADITIONALDLL_API void InitLocation(Location*);
}

double GetDistance(Location loc1, Location loc2) {
   printf_s("[unmanaged] loc1(%d,%d)", loc1.x, loc1.y);
   printf_s(" loc2(%d,%d)\n", loc2.x, loc2.y);

   double h = loc1.x - loc2.x;
   double v = loc1.y = loc2.y;
   double dist = sqrt( pow(h,2) + pow(v,2) );

   return dist;
}

void InitLocation(Location* lp) {
   printf_s("[unmanaged] Initializing location...\n");
   lp->x = 50;
   lp->y = 50;
}

which is basically copy/pasted from the MSDN example. I then compiled it with EHsc selected from the Properties window. I read that I have to compile it with LD as well, but I couldn't find any LD option in the Properties window, so I assumed it is automatically done because I have previously selected this to be a DLL.

The DLL is compiled as C++ I believe, I haven't change it. I'm using the default MS Visual Studio settings.

I was able to solve the problem. Thanks a lot gusano79 for your tip.

The way to solve it is:
Right-Click the DLL project
Select Properties
Go to C/C++
Advanced
In the dropdown list of Calling Convention, choose __stdcall

This problem is now solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.