14

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

4 回答 4

17

你可以这样想:

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

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

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

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

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

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

于 2011-06-13T18:22:29.247 回答
6

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

于 2011-06-13T18:23:48.130 回答
3

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

于 2011-06-13T18:07:11.923 回答
1

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

于 2014-05-15T16:36:01.950 回答