3

I have written a C DLL and some C# code to test including this DLL and executing functions from it. I am not too familiar with this process, and am receiving a PInvokeStackImbalance exception whenever my DLL function is called from the C# source code. The code is as follows (I have commented most code out to isolate this problem):

C# Inclusion code:

using System;
using System.Runtime.InteropServices;
using System.IO;

namespace TestConsoleGrids
{
    class Program
    {

        [DllImport("LibNonthreaded.dll", EntryPoint = "process")]
            public unsafe static extern void process( long high, long low);

        static void Main(string[] args)
        {
            System.Console.WriteLine("Starting program for 3x3 grid");

            process( (long)0, (long)0 );

            System.Console.ReadKey();
        }
    }
}

C++ DLL Function Code

extern "C" __declspec(dllexport) void process( long high, long low );

void process( long high, long low )
{
    // All code commented out
}

Visual Studio generated dllmain code (I do not understand this construct, so I am including it)

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 switch (ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:
 case DLL_THREAD_ATTACH:
 case DLL_THREAD_DETACH:
 case DLL_PROCESS_DETACH:
  break;
 }
 return TRUE;
}

The details of the exception are:

A call to PInvoke function 'TestConsoleGrids!TestConsoleGrids.Program::process' 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.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Mason Blier
  • 140
  • 2
  • 11
  • You don't need the unsafe keyword on the pinvoke signature. PInvoke handles the marshalling from .net to native – zebrabox Feb 20 '10 at 20:13
  • 2
    Have you done what the details tells you to? Checked the calling convention? Check the documentation for the DllImportAttribute class, http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx, it has a CallingConvention property, try setting it to CallingConvention.Cdecl. [DllImport(..., CallingConvention=Callingconvention.Cdecl)] – Lasse V. Karlsen Feb 20 '10 at 20:40
  • Thank you Lasse! That is exactly what the problem was. I have been mostly following tutorials, and none of them have mentioned this. – Mason Blier Feb 20 '10 at 20:47

3 Answers3

5

The calling convention is wrong. If removing the int arguments doesn't trip the MDA then it is Cdecl:

 [DllImport("LibNonthreaded.dll", CallingConvention = CallingConvention.Cdecl)]
 public static extern void process(int high, int low);

This isn't the standard calling convention for exported DLL functions, you might consider changing it in the C/C++ code, if you can.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
2

In C++ a long is 32 bit. In C# it's 64 bit. Use int in your C# declaration.

You could also try adding __stdcall to the C++ function. See: What is __stdcall?

Community
  • 1
  • 1
Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
  • Alright fantastic insight, and you must be correct about the parameters as removing them completely resolves the problem. Simply declaring them as int in C# does not though. – Mason Blier Feb 20 '10 at 20:22
0

in C# long means 64 bit int while in C++ long means 32 bit int, you need to change your pinvoke declaration to

 [DllImport("LibNonthreaded.dll", EntryPoint = "process")]
     public unsafe static extern void process( int high, int low);

You could also try changing your C++ declaration to stdcall, that's the calling convention used by most exported functions in the Windows environment.

 __stdcall  __declspec(dllexport) void process( long high, long low );
John Knoeller
  • 33,512
  • 4
  • 61
  • 92
  • Unfortunate this does not resolve the problem. Thank you for directing me to Type Marshalling however, I am researching this now. – Mason Blier Feb 20 '10 at 20:24