Использовать вложенные функции в качестве обратных вызовов с функциями Windows API? - PullRequest
0 голосов
/ 01 октября 2018

У меня есть следующий код, это работает.

import core.sys.windows.windows: EnumWindows;
import std.stdio: writeln;

void*[] hWndList;

extern (Windows) int callback(void* hWnd, long /* lParams */ ) nothrow {
    hWndList ~= hWnd;

    return true;
}

void main() {
    EnumWindows(&callback, 0);

    writeln(hWndList);
}

Я надеялся, что смогу использовать что-то более похожее на синтаксис JavaScript: (void* hWnd, long) => {}.

Я пробовал это, но я 'Я получаю ошибки с подписью, она говорит, что функция является делегатом, и, очевидно, Windows API не может принять делегата.

import core.sys.windows.windows: EnumWindows;
import std.stdio: writeln;

void main() {
    void*[] hWndList;

    EnumWindows((void* hWnd, long /* lParams */ ) nothrow {
        hWndList ~= hWnd; return true;
    }, 0);

    writeln(hWndList);
}

Я не собираюсь даже вставлять ошибку компилятора, потому что я очень четкопоступить неправильно.

Конечно, нет ничего плохого в определении каждого обратного вызова как отдельной функции, но возникает проблема с присвоением им имен.Мне также не нравится, как мой код выглядит.

Спасибо.

1 Ответ

0 голосов
/ 02 октября 2018

Я понял, что могу привести делегата (или лямбду) к правильной подписи, указанной в документации MSDN для EnumWindowsProc.

Я также не осознавал, что этобыло очень плохой практикой обращаться к фрейму программы D, неявно используя hWndList из глобальной области видимости.

Это то, что я использовал для создания правильной подписи.

alias EnumWindowsProc = extern (Windows) int function(HWND, LPARAM) nothrow;

ЗатемЯ обнаружил, что псевдоним уже существует как ENUMWINDOWSPROC в заголовках MinGW в core.sys.windows.windows в строке 2483 (на момент написания).

extern (Windows) nothrow {
    ...
    alias BOOL function(HWND, LPARAM) ENUMWINDOWSPROC;
    ...
}

Чтобы решить проблему неявной передачи кадра D, яиспользовал cast(LPARAM) &hWndList в качестве lParam в EnumWindows.

Это стало проблемой использования указателя сейчас.Я знаю, что это, вероятно, неправильно, любые предложения приветствуются, но я привел его к указателю.

*(cast(HWND[]*) lParam)

И полный код выглядит примерно так.Очевидно, что для начала это был лишь минимальный пример, так что вы можете присвоить приведенный указатель чему-либо, чтобы он был менее запутанным при использовании переменной из lParams.

import core.sys.windows.windows: EnumWindows, ENUMWINDOWSPROC;
import std.stdio: writeln;

void main() {
    HWND[] hWndList;

    EnumWindows(cast(ENUMWINDOWSPROC) (HWND hWnd, LPARAM lParam) {
        *(cast(HWND[]*) lParam) ~= hWnd;
        return true;
    }, cast(LPARAM) &hWndList);

    writeln(hWndList);
}

Надеюсь, это кому-нибудь поможетпотому что это было чертовски непонятно для меня (все еще не уверен, что я понимаю логику указателя).

Спасибо Борису-Барборису на форумах D за то, что дали мне кое-что для работы.

https://forum.dlang.org/post/xxklxaajptppockvazeo@forum.dlang.org

...