【问题标题】:CDecl cleanup code in explicitly linked DLL显式链接 DLL 中的 CDecl 清理代码
【发布时间】:2015-05-28 03:01:42
【问题描述】:

我在非托管 Win32 DLL 中有一个函数,它接受可变数量的参数,因此需要为 __cdecl 而不是 __stdcall 或任何其他调用约定。目前我正在显式链接到 DLL(也就是说,我使用的是 LoadLibraryGetProcAddress,而不是链接到 DLL 的 .lib 文件)。

我可以很好地调用该函数,但由于它是cdecl,我需要在每次调用后添加以下内联汇编指令:

retVal = addVecs(v1, v2, v3, v4);
__asm add esp, 64 ;Sizeof VECTOR struct is 16 bytes
printf("The sum of all these vectors is:\n\tMagnitude: %f\n\tDirection (radians): %f\n\n", retVal.mag, retVal.dir);

如果我不包含内联程序集,那么程序在调用 addVecs 后会崩溃。

有没有什么方法可以编写 EXE 或 DLL,从而不需要内联汇编指令?例如,printf 也是一个 __cdecl 函数,但我不需要编写内联汇编来确保在每次调用后清理堆栈。

【问题讨论】:

  • 调用GetProcAddress后存储函数指针时,是否存储在包含__cdecl的指针中?
  • __cdecl 通常不是 Win32 中的默认调用约定吗? (至少对于使用 MSVC 编译的代码,即使 Win32 API 本身不使用它)
  • @immibis 您可以将默认调用约定指定为编译器选项。这不是你应该依赖的东西。尤其是在加载 DLL 时,您应该始终是明确的。

标签: c++ c dll calling-convention cdecl


【解决方案1】:

您需要确保addVecs 的调用约定是正确的。明确这一点是值得的,不要依赖编译器的默认值。

typedef VECTOR (__cdecl *addVecs_ptr)( VECTOR, VECTOR, VECTOR, VECTOR );

static addVecs_ptr addVecs = NULL;

如果您使用过这样的 typedef,它可以让您稍后在加载地址时轻松进行转换:

addVecs = (addVecs_ptr) GetProcAddress( hSomeDllHandle, "addVecs" );

【讨论】:

  • 帮助很大!我已经习惯在使用 GetProcAddress 时输入标准的 CALLBACK* 宏,但我忘记了这是 __stdcall 的#define
猜你喜欢
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多