declspec and stdcall vs declspec only
Asked Answered
H

4

16

I'm a new person to C++ dll import topic and may be my question is very easy but I can not find it on google.

I have a very simple C++ win32 dll:

#include <iostream>

using namespace std;

extern "C"
{
    __declspec(dllexport) void __stdcall DisplayHellowFromDLL()
    {
        cout<<"Hi"<<endl;
    }
}

When I call this method from C# I do not have any problem, here is C# code

namespace UnmanagedTester
{
    class Program
    {
        [DllImport(@"C:\CGlobalDll")]
        public static extern void DisplayHellowFromDLL();

        static void Main(string[] args)
            {
                Console.WriteLine("This is C# program");
                DisplayHellowFromDLL();
            }
        }
    }

As I expected the output is: "This is C# program" "Hi".

Now if I change the declaration of C function as:

__declspec(dllexport) void DisplayHellowFromDLL()

without __stdcall, I do not have any problem as well, and the question is:

When do I really need __declspec(dllexport) TYPE __stdcall and when I can use only __declspec(dllexport) TYPE ?

Thanks a lot.

Hydrophobia answered 13/6, 2011 at 18:3 Comment(0)
L
4

You need to specify the calling convention if you compile the calling code with some other convention. Otherwise the default will work.

Laval answered 13/6, 2011 at 18:7 Comment(0)
B
19

You can think of it like this:

  1. __declspec(dllexport) declares your function as a public function that your DLL exports;

  2. __stdcall is a rather low-level detail that refers to the "calling convention" adopted by that function; specifically, __stdcall means that the callee cleans the stack;

  3. alternative to __stdcall is __cdecl, which means: the caller cleans the stack.

__cdecl is the "natural" C calling convention; it supports the definition of vararg functions (like printf).

__stdcall is the default calling convention for DLL functions, so you don't need specify it if you are only going to call those functions through their DLL API.

This should explain what you are observing.

Butz answered 13/6, 2011 at 18:22 Comment(0)
F
7

It works by accident because the function doesn't take any arguments. As soon as you do this on a function that does take arguments you'll start running out of luck. The call will leave the stack imbalanced, very unhealthy. You'd get the pInvokeStackImbalance MDA warning when you debug. An imbalanced stack can otherwise go unnoticed for a while, it tends to crash your program in the Release build.

Fenestella answered 13/6, 2011 at 18:23 Comment(4)
Thanks for reply Hans. I just tried to do it with function that accept arguments like __declspec(dllexport) int Add(int a, int b){ return (a+b); } and I did not get any warning or errors.Hydrophobia
Set the platform target to x86.Fenestella
Hans, I did it on my VS2008, run without any exceptions or warnings.Hydrophobia
It's possible that p/invoke is guessing the calling convention based on the mangled name (leading underscore usually indicates cdecl, while trailing @count indicates stdcall)Wrest
L
4

You need to specify the calling convention if you compile the calling code with some other convention. Otherwise the default will work.

Laval answered 13/6, 2011 at 18:7 Comment(0)
S
1

Ilya, you can also set the default calling convention in Project Properties -> Configuration Properties -> C/C++ -> Advanced -> Calling Convention. If the default calling convention in your project is already set to __stdcall (/Gz), then adding __std

Sweat answered 15/5, 2014 at 16:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.