C++0x 是否支持 __stdcall 或 extern "C"不捕获任何 lambda?

发布于 2024-09-03 19:15:37 字数 1136 浏览 2 评论 0 原文

昨天我在想是否可以利用C++0x lambda函数的便利性来为Windows API函数编写回调。

例如,如果我想使用 lambda 作为 EnumChildProcEnumChildWindows ?类似于:

EnumChildWindows(hTrayWnd, CALLBACK [](HWND hWnd, LPARAM lParam) {
        // ...
        return static_cast<BOOL>(TRUE); // continue enumerating
    }, reinterpret_cast<LPARAM>(&myData));

另一个用途是为 C 例程编写 extern "C" 回调。例如:

my_class *pRes = static_cast<my_class*>(bsearch(&key, myClassObjectsArr, myClassObjectsArr_size, sizeof(my_class), extern "C" [](const void *pV1, const void *pV2) {
        const my_class& o1 = *static_cast<const my_class*>(pV1);
        const my_class& o2 = *static_cast<const my_class*>(pV2);

        int res;
        // ...
        return res;
    }));

这可能吗?

我可以理解捕获变量的 lambda 永远不会与 C 兼容,但至少在我看来,capture-nothing lambda 可以兼容。

Yesterday I was thinking about whether it would be possible to use the convenience of C++0x lambda functions to write callbacks for Windows API functions.

For example, what if I wanted to use a lambda as an EnumChildProc with EnumChildWindows? Something like:

EnumChildWindows(hTrayWnd, CALLBACK [](HWND hWnd, LPARAM lParam) {
        // ...
        return static_cast<BOOL>(TRUE); // continue enumerating
    }, reinterpret_cast<LPARAM>(&myData));

Another use would be to write extern "C" callbacks for C routines. E.g.:

my_class *pRes = static_cast<my_class*>(bsearch(&key, myClassObjectsArr, myClassObjectsArr_size, sizeof(my_class), extern "C" [](const void *pV1, const void *pV2) {
        const my_class& o1 = *static_cast<const my_class*>(pV1);
        const my_class& o2 = *static_cast<const my_class*>(pV2);

        int res;
        // ...
        return res;
    }));

Is this possible?

I can understand that lambdas that capture variables will never be compatible with C, but it at least seems possible to me that capture-nothing lambdas can be compatible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

临风闻羌笛 2024-09-10 19:15:37

没有捕获的 Lambda可以隐式转换指向函数的指针(通过闭包类型定义的非显式转换函数)。

FCD似乎没有指定该函数指针类型的函数类型具有什么语言链接,因此如果需要将此函数指针传递给C函数,则C++函数和C函数的调用约定需要相同。我相信在 Windows 上,情况确实如此。因此,您应该能够将 lambda 传递给

typedef void(*callbackType)(void *userData);
extern "C" void someCFunction(callbackType callback);

int main() {
  someCFunction([](void *userData) { /* ... */ });
}

5.1.2/6 处的 Windows API 函数 FCD 措辞:

没有 lambda 捕获的 lambda 表达式的闭包类型具有公共非虚拟非显式 const 转换函数,用于指向具有与闭包类型的函数调用运算符相同的参数和返回类型的函数。此转换函数返回的值应是函数的地址,该函数在调用时具有与调用闭包类型的函数调用运算符相同的效果。

我认为最终标准应该有一个注释,指出有一个到 C 链接函数指针和 C++ 链接函数指针的转换函数,因为到 C 函数指针的可转换性是此功能的目标之一。

Lambdas without a capture are implicitly convertible to a pointer to function (by a non-explicit conversion function defined by the closure type).

The FCD does not seem to specify what language linkage the function type of that function pointer type has, so if you need to pass this function pointer to C functions, the calling convention of C++ functions and C functions need to be the same. I believe that on Windows, that is the case though. So you should be able to pass the lambda to Windows API functions

typedef void(*callbackType)(void *userData);
extern "C" void someCFunction(callbackType callback);

int main() {
  someCFunction([](void *userData) { /* ... */ });
}

FCD wording at 5.1.2/6:

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.

I think the final Standard should have a note that says that there is a conversion function to both C linkage function pointers and C++ linkage function pointers, as convertibility to C function pointers is one of the goal of this functionality.

薄荷梦 2024-09-10 19:15:37

函数指针的语言链接源自无捕获 lambda 的转换,该转换未在 C++11 标准中指定,但已在 缺陷报告 1557 内容如下:

5.1.2 [expr.prim.lambda]第6段没有指定闭包类型的转换函数的函数类型的语言链接。

决议是语言链接应该是 C++:

不带 lambda 捕获的 lambda 表达式的闭包类型具有公共非虚拟非显式 const 转换函数,用于指向具有 C++ 语言链接的函数指针 (7.5 [dcl.link])。与闭包类型的函数调用运算符具有相同的参数和返回类型。返回值...

我们可以在 C++14 标准草案中找到这种语言,因为状态是 DRWP ,这似乎不适用于 C++11。

The language linkage of the function pointer results from a conversion of a capture-less lambda was not specified in the C++11 standard but was addressed in defect report 1557 which says:

5.1.2 [expr.prim.lambda] paragraph 6 does not specify the language linkage of the function type of the closure type's conversion function.

and the resolution was that the language linkage should be C++:

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function with C++ language linkage (7.5 [dcl.link]). having the same parameter and return types as the closure type's function call operator. The value returned...

we can find this language in the draft C++14 standard, since the status is DRWP it seems like this does not apply to C++11.

唱一曲作罢 2024-09-10 19:15:37

没有特别充分的理由表明这不应该扩展到捕获 lambda。它需要一些动态代码生成,但它不应该超出编译器编写者的智慧,并且它将使与旧 C API 的互操作变得更容易——不再需要通过无类型 void* 传递参数(这不是所有的) API 甚至提供)。

There's no particularly good reason that this shouldn't be extended to capturing lambdas. It requires some dynamic code generation, but it shouldn't be beyond the wit of compiler writers, and it would make interop with old C APIs orders of magnitude easier--no more need to pass parameters through untyped void*s (which not all APIs even offer).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文