c++ - 解释这是如何工作的以及如何转换为 constexpr
问题描述
我读到在宏上使用 constexpr 是最佳实践,所以我想知道为什么会这样?以及如何将其转换为使用 constexpr。
我尝试创建一个带有 5 个参数的模板。像这样-
constexpr auto FUNC(t1 dll, t2 name, t3 callingret, t4 args, t5 address)
{
}
#define FUNCPTR(dll, name, callingret, args, address) \
__declspec(naked) callingret dll##_##name##args \
{ \
static DWORD f##dll##_##name = NULL; \
if(f##dll##_##name == NULL) \
{ \
__asm { pushad } \
f##dll##_##name = Offset(address); \
__asm { popad } \
} \
__asm jmp [f##dll##_##name] \
}
解决方案
在 .NET 中,您可以使用 DLLImport 扩展来重命名从 DLL 导入的函数。
using namespace System;
using namespace System::Runtime::InteropServices;
typedef void* HWND;
[DllImport("user32", EntryPoint = "MessageBoxA")]
extern "C" int MsgBox(
HWND hWnd, String* lpText, String* lpCaption, unsigned int uType);
如果你有地址,就像你假设的原始代码一样,你也可以初始化一个函数指针,例如
const auto user32_MessageBox =
(int(WINAPI *)( HWND, LPCWSTR, LPCWSTR, UINT )) address;
这里的确切类型取决于来自哪里address
。例如,如果您从LoadLibrary()
and获得指针GetProcAddress()
,则该地址是在运行时从系统调用返回的。任何依赖它的东西都不可能constexpr
。
将地址的类型声明为 aDWORD
并使用 inlineasm
是完全不可移植的。上面的版本只有在类型address
正确的情况下才可移植,但是您使用的获取地址的方法应该确保这一点。
如果没有宏,代码无法轻松完成的一件事是将参数合并到标识符中。但是,这应该不是必需的。(正如 Ben Voight 指出的那样,宏扩展为的函数中的局部变量不需要具有唯一名称。)
推荐阅读
- ios - Swift 无法为导航栏按钮项设置动画
- laravel - 运行数据库播种器时获取类不存在错误
- ionic4 - 使用 CMD 构建一个 Ionic 4 Capacitor 应用程序,就像 Cordova
- python - 获取运动员人数
- c - strtok_s return incorrect data inside windbg
- azure-cosmosdb - 从 Cosmos SQL 中获取分组(不同的?!?)值数组
- jquery - 在jquery中的2个元素之间添加css
- c - 我该如何解决这个堆栈溢出错误?
- c# - 在忽略工作日和节假日的 TimeSpan 之后查找 DateTime
- c# - 着色器场景中的立方体贴图天空盒