declspec和stdcall vs仅限于declspec

时间:2011-06-13 18:03:58

标签: c# c++ dllimport stdcall

我是C ++ dll导入主题的新人,可能我的问题很简单,但我无法在谷歌上找到它。

我有一个非常简单的C ++ win32 dll:

#include <iostream>

using namespace std;

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

当我从C#调用此方法时,我没有任何问题,这里是C#代码

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

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

正如我所料,输出是:“这是C#程序”“嗨”。

现在,如果我将C函数的声明更改为:

__declspec(dllexport) void DisplayHellowFromDLL()

没有__stdcall,我也没有任何问题,问题是:

我什么时候才需要__declspec(dllexport)TYPE __stdcall,什么时候才能使用__declspec(dllexport)TYPE?

非常感谢。

4 个答案:

答案 0 :(得分:14)

你可以这样想:

  1. __declspec(dllexport)将您的函数声明为您的DLL导出的公共函数;

  2. __stdcall是一个相当低级的细节,指的是该函数采用的“调用约定”;具体来说,__stdcall表示被调用者清理堆栈;

  3. 替代__stdcall__cdecl,这意味着:调用者清理堆栈。

  4. __cdecl是“自然的”C调用约定;它支持vararg函数的定义(如printf)。

    __stdcall是DLL函数的默认调用约定,因此如果您只是通过DLL API调用这些函数,则不需要指定它。

    这应该解释你在观察什么。

答案 1 :(得分:6)

它是偶然的,因为该函数不带任何参数。只要你在 接受参数的函数上执行此操作,您就会开始运气不好。通话将使堆栈失衡,非常不健康。调试时会得到pInvokeStackImbalance MDA warning。不平衡的堆栈否则会被忽略一段时间,它会使发布版本中的程序崩溃。

答案 2 :(得分:3)

如果使用其他约定编译调用代码,则需要指定调用约定。否则默认将起作用。

答案 3 :(得分:0)

Ilya,你也可以在Project Properties中设置默认的调用约定 - &gt;配置属性 - &gt; C / C ++ - &gt;高级 - &gt;召集公约。 如果项目中的默认调用约定已设置为__stdcall(/ Gz),则添加__std