【问题标题】:declspec and stdcall vs declspec only仅 declspec 和 stdcall 与 declspec
【发布时间】:2011-09-14 03:00:51
【问题描述】:

我是 C++ dll 导入主题的新手,我的问题可能很简单,但我在 google 上找不到。

我有一个非常简单的 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 ?

非常感谢。

【问题讨论】:

    标签: c# c++ dllimport stdcall


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      它的工作是偶然的,因为该函数不接受任何参数。一旦你对一个确实接受参数的函数执行此操作,你就会开始走运。该调用将使堆栈不平衡,非常不健康。调试时你会得到pInvokeStackImbalance MDA warning。不平衡的堆栈可能会在一段时间内被忽视,它往往会使您的程序在发布版本中崩溃。

      【讨论】:

      • 感谢汉斯的回复。我只是尝试使用接受像 __declspec(dllexport) int Add(int a, int b){ return (a+b); 这样的参数的函数来做到这一点} 并且我没有收到任何警告或错误。
      • 将平台目标设置为 x86。
      • 汉斯,我是在我的VS2008上做的,运行没有任何异常或警告。
      • p/invoke 可能会根据损坏的名称猜测调用约定(前导下划线通常表示 cdecl,而尾随 @count 表示 stdcall)
      【解决方案3】:

      你可以这样想:

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

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

      3. __stdcall 的替代品是__cdecl,这意味着:调用者清理堆栈。

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

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

      这应该可以解释您所观察到的内容。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-25
          • 2020-02-15
          相关资源
          最近更新 更多