首页 文章

declspec和stdcall vs declspec only

提问于
浏览
13

我是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 回答

  • 14

    Ilya,您还可以在项目属性 - >配置属性 - > C / C - >高级 - >呼叫约定中设置默认调用约定 . 如果项目中的默认调用约定已设置为__stdcall(/ Gz),则添加__std

  • 6

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

  • 0

    你可以这样想:

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

    • __stdcall 是一个相当低级的细节,指的是该函数采用的"calling convention";具体来说, __stdcall 表示被调用者清理堆栈;

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

    __cdecl 是"natural" C调用约定;它支持vararg函数的定义(如printf) .

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

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

  • 3

    它是偶然的,因为该函数不带任何参数 . 一旦你在一个带参数的函数上执行此操作,你就会在调试时获得pInvokeStackImbalance MDA warning . 不 balancer 的堆栈否则会被忽视一段时间,它往往会在Release版本中使程序崩溃 .

相关问题