Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ stdcall的优点/用途是什么?_C++_Stdcall - Fatal编程技术网

C++ stdcall的优点/用途是什么?

C++ stdcall的优点/用途是什么?,c++,stdcall,C++,Stdcall,在发布这个问题之前,我已经阅读了一些文档,并观看了一些视频来理解\uu stdcall。到目前为止,我已经了解到这是一种调用约定,并指定在堆栈上从右向左推送参数。这也表示何时清除堆栈 但是我仍然无法理解我应该使用\uu stdcall的优点和情况 我遇到了以下代码,在OPC-UA客户端关闭时调用。我知道这应该遵循\uu stdcall调用约定,但为什么呢?如果未为以下方法指定\u stdcall,会发生什么情况 OpcUa_StatusCode __stdcall opcua_client::o

在发布这个问题之前,我已经阅读了一些文档,并观看了一些视频来理解
\uu stdcall
。到目前为止,我已经了解到这是一种调用约定,并指定在堆栈上从右向左推送参数。这也表示何时清除堆栈

但是我仍然无法理解我应该使用
\uu stdcall
的优点和情况

我遇到了以下代码,在OPC-UA客户端关闭时调用。我知道这应该遵循
\uu stdcall
调用约定,但为什么呢?如果未为以下方法指定
\u stdcall
,会发生什么情况

OpcUa_StatusCode __stdcall opcua_client::onShutdownMessage(OpcUa_Handle hApplication, OpcUa_Handle hSession, OpcUa_String strShutdownMessage, void* extraParam)
{
    opcua_client* pOpcClient = NULL;
    if (extraParam)
    {
        try
        {
            pOpcClient = qobject_cast <opcua_client*>((QObject*)extraParam);
            throw(55);
        }
        catch (int exeption)
        {

        }
    }

    OpcUa_StatusCode uStatus = OpcUa_Good;

    QString strShutDownMsg = QString::fromUtf8(OpcUa_String_GetRawString(&strShutdownMessage));
    bool bOK;
    OpcUa_StatusCode uClientLibStatus = uClientLibStatus = strShutDownMsg.toUInt(&bOK, 16);

    if (pOpcClient)
    {
        if (uClientLibStatus > 0)
            pOpcClient->process_onShutdownMessage(uClientLibStatus);
    }
    else
    {
        return uStatus;
    }

    return uStatus;
}
OpcUa_StatusCode\uu stdcall OpcUa_client::onShutdownMessage(OpcUa_Handle hApplication、OpcUa_Handle hSession、OpcUa_String strShutdownMessage、void*extraParam)
{
opcua_client*pOpcClient=NULL;
if(外部参数)
{
尝试
{
pOpcClient=QoObject_cast((QoObject*)外部参数);
投掷(55);
}
捕获(整数例外)
{
}
}
OpcUa_状态代码uStatus=OpcUa_良好;
QString strShutDownMsg=QString::fromUtf8(OpcUa_String_GetRawString(&strShutdownMessage));
布尔博克;
OpcUa_状态代码uClientLibStatus=uClientLibStatus=strshutdownmg.toUInt(&bOK,16);
if(pOpcClient)
{
如果(uClientLibStatus>0)
pOpcClient->process_onShutdown消息(uClientLibStatus);
}
其他的
{
返回uStatus;
}
返回uStatus;
}

opcua\u客户端::onShutdownMessage
看起来像回调函数。也就是说,发送给某个API的函数,该API在以后调用该函数。然后回调函数必须具有API所期望的调用约定,在本例中为
\uu stdcall
。由于
\uu stdcall
是Win32平台上的默认调用约定,因此在为Win32构建时不必指定它。

调用方必须遵循函数调用约定。如果它存在,那么这个函数的某个调用者将假定它必须以特定的方式被调用。当您有回调函数时,这通常很重要

除此之外,
stdcall
通过将参数清理代码从调用者移动到被调用者(可在x86上使用),旨在减少与
cdecl
相比的代码大小

这是一个旧的IA-32体系结构微优化。MSVC在其他体系结构上也接受
\uu stdcall
关键字,但它可以

检查此示例:

__declspec(noinline) int sum(int a, int b)
{
    return a + b;
}

int add1(int a)
{
    return sum(a, 1);
}
MSVC将其编译为:

int sum(int,int) PROC
  mov eax, DWORD PTR _a$[esp-4]
  add eax, DWORD PTR _b$[esp-4]
  ret 0 ; this instruction will be replaced
int sum(int,int) ENDP

int add1(int) PROC
  push 1
  push DWORD PTR _a$[esp]
  call int sum(int,int)
  add esp, 8 ; this instruction will be removed
  ret 0
int add1(int) ENDP
和带有
stdcall
的版本:

__declspec(noinline) int __stdcall sum(int a, int b)
{
    return a + b;
}

int add1(int a)
{
    return sum(a, 1);
}
其汇编目的是:

int sum(int,int) PROC
  mov eax, DWORD PTR _a$[esp-4]
  add eax, DWORD PTR _b$[esp-4]
  ret 8 ; 0 argument replaced with 8
int sum(int,int) ENDP

int add1(int) PROC
  push 1
  push DWORD PTR _a$[esp]
  call int sum(int,int)
  ret 0 ; extra instruction is missing here
int add1(int) ENDP

请注意第二个示例如何使用
ret 8
,而调用者没有额外的
add esp,8

,这是32位代码中操作系统和COM库的标准调用约定。OPC是基于COM的,因此预计会看到大量的STDC。尽管onShutdownMessage()不是标准接口函数之一。也许您使用的工具包指示stdcall,这一点都不奇怪。