标签: cdecl

stdcall和cdecl

除其他外,还有两种类型的调用约定--stdcallcdecl.我对他们几乎没有问题:

  1. 当调用cdecl函数时,调用者如何知道它是否应该释放堆栈?在调用站点,调用者是否知道被调用的函数是cdecl还是stdcall函数?它是如何工作的 ?调用者如何知道它是否应该释放堆栈?或者它是连接者的责任吗?
  2. 如果声明为stdcall的函数调用一个函数(其调用约定为cdecl),或者相反,那么这是不合适的吗?
  3. 一般来说,我们可以说哪个调用会更快--cdecl或stdcall?

c++ cdecl stdcall

82
推荐指数
4
解决办法
10万
查看次数

为什么Cdecl调用在"标准"P/Invoke公约中经常不匹配?

我正在开发一个相当大的代码库,其中C++函数是从C#调用P /.

我们的代码库中有很多调用,比如......

C++:

extern "C" int __stdcall InvokedFunction(int);
Run Code Online (Sandbox Code Playgroud)

使用相应的C#:

[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
    private static extern int InvokedFunction(IntPtr intArg);
Run Code Online (Sandbox Code Playgroud)

我已经搜索了网(在我有能力的范围内),因为为什么存在这种明显的不匹配.例如,为什么C#中有Cdecl,而C++中有__stdcall?显然,这会导致堆栈被清除两次,但是,在这两种情况下,变量都以相同的相反顺序被压入堆栈,这样我就不会看到任何错误,尽管在发生的情况下可能会清除返回信息.在调试期间尝试跟踪?

来自MSDN:http: //msdn.microsoft.com/en-us/library/2x8kf7zx%28v=vs.100%29.aspx

// explicit DLLImport needed here to use P/Invoke marshalling
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl,  CharSet = CharSet::Ansi)]

// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);
Run Code Online (Sandbox Code Playgroud)

再一次,extern "C"C++代码和CallingConvention.CdeclC#中都有.为什么不CallingConvention.Stdcall呢?或者,此外,为什么__stdcallC++中存在?

提前致谢!

c# c++ pinvoke cdecl stdcall

53
推荐指数
2
解决办法
2万
查看次数

你怎么读C声明?

我听说过一些方法,但都没有卡住.我个人试图避免C中的复杂类型,并尝试将它们分解为组件typedef.

我现在面临着从一个所谓的"三星级程序员"维护一些遗留代码的问题,而且我很难阅读一些***代码[] [].

你如何阅读复杂的C声明?

c typedef cdecl

42
推荐指数
4
解决办法
6514
查看次数

"cdecl"代表什么?

是的,我知道"cdecl"是一个突出的调用约定的名称,所以请不要向我解释调用约定.我要问的是缩写(?)"cdecl"实际上代表什么.我认为这是一个糟糕的命名选择,因为乍一看它提醒了一个"C声明者"(C的一个相当独特的句法方面).实际上,有一个名为cdecl的程序,其唯一目的是解密C声明.但据我所知,C声明符语法与调用约定完全无关.

简化版:"stdcall"代表"标准调用约定"."cdecl"代表什么?

c c++ cdecl calling-convention nomenclature

23
推荐指数
4
解决办法
1万
查看次数

我为什么不使用__fastcall而不是标准__cdecl?

我会听一些人说__fastcall比这更快__cdecl并且__stdcall导致它将两个参数放入寄存器,而不是其他一个调用; 但是,另一方面,这不是C中使用的标准.

我想知道什么是__fastcall不合适的,就像C中的标准,以及何时我将在我的代码中使用它.

c c++ function-calls cdecl fastcall

10
推荐指数
1
解决办法
3588
查看次数

有没有办法在没有.*或 - >*运算符的情况下调用成员函数

下面D::foo通过指向成员函数调用函数的方法将产生错误:必须使用.*->*调用'f(...)'中的指针到成员函数... 当然这不是我们如何调用指针到 -成员职能.

正确的呼叫方式是(d.*f)(5);OR(p->*f)(5);

我的问题是,'有没有办法在没有左侧的类对象的情况下调用类的成员函数?我想知道我们是否可以将class object(this)作为常规参数传递?

在我看来,在一天结束时(在汇编/二进制级别),类的所有成员函数都是普通函数,它们应该在n + 1个参数上运行,其中(+ 1表示this)

如果我们谈论D::foo下面的函数,在汇编/二进制级别它应该运行两个参数:

  1. 类对象本身(指向D类对象的指针this)
  2. int.

那么,有没有一种方法(或hack)调用D::foo传递给它的类对象作为函数参数而不是. or -> or .* or ->*在类对象上使用运算符?

示例代码:

#include <iostream>
using namespace std;

class D {
    public:
        void foo ( int a ) {
            cout << "D" << endl;
        }

        int data;
};


//typedef void  __cdecl ( D::*  Func)(int);
typedef void ( D::* …
Run Code Online (Sandbox Code Playgroud)

c++ boost cdecl

10
推荐指数
2
解决办法
2452
查看次数

改变呼叫公约

我有一个第三方C API,需要一个__stdcall回调函数.
我的代码有一个外部提供的 __cdecl回调函数.

我无法将函数指针传递给C-API,因为它们被认为是不同的类型.
绕过类型系统并reinterpret_cast<>自然地使用会导致运行时错误.

下面是一个例子在这里:

// C-API
// the stdcall function pointer type:
typedef CTMuint(__stdcall *CTMwritefn)(const void *aBuf, CTMuint aCount, void *aUserData);

// A function needing the callback: 
CTMEXPORT void __stdcall ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, void *aUserData, int *newvertexindex);
                                                            ^^^^^^^^^^^^^^^^^^^

//////////////////////////////////////////////////////////////////////////////

// C++
CTMuint __cdecl my_func(const void *aBuf, CTMuint aCount, void *aUserData);

// I want to call here:
ctmSaveCustom(context, my_func, &my_data, nullptr);
//                     ^^^^^^^
Run Code Online (Sandbox Code Playgroud)

有没有办法安全地将一个调用约定的函数转换和/或包装到另一个调用约定中?

我确实通过传递一个调用第二个捕获lambda的casted …

c++ function-pointers cdecl calling-convention stdcall

10
推荐指数
1
解决办法
1268
查看次数

PInvoking C++ DLL时出现AccessViolationException(cdecl调用约定问题?)

我花了一整天研究这个,而且我不是更聪明的:

我有一个C#DLL,PInvokes C++ DLL中的方法.在调试模式下编译时我没有遇到任何问题,但在Release模式下编译时,我得到一个AccessViolationException.谷歌搜索这个问题告诉我,它可能是不合规的调用约定的问题.现在代码在C#中看起来像这样:

[return: MarshalAs(UnmanagedType.U1)]
[DllImport("Native.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern Boolean AMethod(Int32 mode, byte frame);
Run Code Online (Sandbox Code Playgroud)

在C++中:

extern "C" {
     DLL_EXPORT bool AMethod(int mode, BYTE frame)
     {
      ...
     }
}
Run Code Online (Sandbox Code Playgroud)

我已经设置C++项目使用VS2010中的__cdecl调用约定进行编译,但我仍然得到AccessViolationException,我不知道我还能做什么.我应该注意我的C++ DLL使用第三方DLL,我不知道他们使用什么调用约定.

任何帮助,将不胜感激!

哦,我的开发机器上没有例外,只在我的目标系统上.

c# c++ pinvoke cdecl access-violation

7
推荐指数
1
解决办法
1689
查看次数

结构如何作为参数传递给汇编

结构如何作为参数传递?

由于结构的大小比正常大,各个字段是否顺序通过?

如果是这样,它们是否与正常参数相反?

他们在cdecl和stdcall之间有什么区别吗?

x86 assembly cdecl stdcall

7
推荐指数
1
解决办法
3158
查看次数

C 调用约定:谁在可变参数函数与普通函数中清理堆栈?

有一些调用约定(例如pascalstdcall),但就我而言,C 确实使用cdecl(C 声明)。这些约定中的每一个在调用者将参数加载到堆栈上的方式上都略有不同,分别是由哪个(调用者/被调用者)进行清理

谈到清理,这是我的问题。我不明白:有三种不同的东西吗?

  1. 堆栈清洁
  2. 将指针移回倒数第二个堆栈帧
  3. 堆栈恢复

或者我应该怎么看他们?

此外,这个问题的目标基本上是可变参数函数如何在像 Pascal 这样的调用约定中工作,或者stdcall被调用者应该在哪里清除/清理/恢复(我不知道哪个操作)堆栈 - 但他不知道有多少参数它会收到。

编辑

为什么将参数压入堆栈的顺序如此重要?您仍然拥有第一个参数(不是来自省略号的稳定参数),它为您提供有关 - 例如 - 变量参数数量的信息。并且还有“监护人”,它可以添加到省略号标点符号中,并且可以用作独立于调用约定的变量部分结束的标记。在这个链接中,如果调用者和被调用者在搞乱它们之前都保存了它们的状态,那么为什么调用者和被调用者都应该恢复这些寄存器的值?不应该只有其中一个(例如调用者)在调用函数之前将它们保存在堆栈中,仅此而已?另外,在同一个链接上

“因此,堆栈指针 ESP 可能会上下移动,但 EBP 寄存器保持固定。这很方便,因为这意味着我们始终可以将第一个参数称为 [EBP + 8],而不管在功能。”

推送的变量和局部变量在内存中是连续的。使用 EBP 推荐他们的优势在哪里?即使堆栈大小发生变化,它们之间也永远不会有一些动态偏移。

我读过的材料之一是这个站点(只是开始),以便更好地了解堆栈帧到底是什么。然后我继续 yt 并找到了这些堆栈概述调用堆栈教程,但他们不知何故错过了我需要的部分。当你调用函数时到底发生了什么(我不明白指令“调用地址”后跟下一个指令a push值到堆栈上,这意味着返回值)。谁来控制退货地址?呼叫者,召集者?被叫方?当被调用者返回时,程序继续执行一条指令,该指令是从寄存器中读取操作或什么?

c x86 cdecl variadic-functions calling-convention

7
推荐指数
1
解决办法
341
查看次数