d如此包装句柄

原文

struct SafeHandle
{
    Unique!void _safe;//.1
    alias _safe this;

    this( HANDLE h )
    {
        this._safe = h;
    }

    ~this()
    {
        if ( cast(HANDLE)_safe !is null )
        if ( cast(HANDLE)_safe != INVALID_HANDLE_VALUE )
        {
            if ( CloseHandle( cast(HANDLE)_safe ) == 0 )
                cast(HANDLE)_safe = null;
        }
    }

    ref HANDLE get()
    {
        return cast( HANDLE )_safe;
    }
}

//使用:

SafeHandle open_keyboard_device2( LPCWSTR path, int* error_number )
{
   ...
   SafeHandle dev_handle =
        CreateFileW(
            path,
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            OPEN_EXISTING,
            0,
            NULL
        );

    if ( dev_handle.get() != INVALID_HANDLE_VALUE )
        ...
   ...
}

void processDevice( ... )
{
    auto dev_handle = open_keyboard_device2( path, &err );
    set_keyboard_indicator2( dev_handle, KEYBOARD_CAPS_LOCK_ON );
    ...
}

如何定义HANDLE变量?从过程返回什么?如何调用?
变量析构时关闭句柄(h)?
明显方法是RAII类型,其中析构器调用CloseHandle

.1,你让Unique成为SafeHandle的成员.我从来没有用过Unique,它有一个bug(或设计问题?):其析构函数如下:

~this()
{
    if (_p !is null)
    {
        destroy(_p);
        _p = null;
    }
}

因为_p是指针,destroy(_p)不会解引用并析构它所指向的内容.这是Unique的一个bug.它应该:

destroy(*_p);

如下包装句柄:

import std;

// 可编译:
alias HANDLE = void*;
alias LPCWSTR = string;
enum INVALID_HANDLE_VALUE = null;
enum FILE_SHARE_READ = 1;
enum FILE_SHARE_WRITE = 2;
enum NULL = null;
enum OPEN_EXISTING = 1000;

// 模拟系统函数
HANDLE CreateFileW(LPCWSTR path, int, int, void*, int, int, void*) {
    auto handle = cast(HANDLE)(new int(42));
    writeln("Created ", handle);
    return handle;
}

int CloseHandle(HANDLE handle) {
    writeln("Closing ", handle);
    return 0;
}

// RAII句柄
struct Handle {
    HANDLE value;

    // 禁止复制和赋值
    @disable this(this);
    @disable typeof(this) opAssign(const(typeof(this)));

    this(HANDLE value) {
        this.value = value;
        writeln("构造:", value);
    }

    ~this() {
        const ret = CloseHandle(value);
        if (ret) {
            stderr.writefln!"关闭%s失败"(value);
        }
    }
}

Handle open_keyboard_device2( LPCWSTR path, int* error_number )
{
   // ...
   HANDLE dev_handle =
        CreateFileW(
            path,
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            OPEN_EXISTING,
            0,
            NULL
        );

   // 要动态创建
   // 指定了唯一的所有者:
   auto result = Handle(dev_handle);
   writeln("退出open_keyboard_device2");
   return result;

    // if ( dev_handle.get() != INVALID_HANDLE_VALUE ) {
    //     // ...
    // }
   // ...
}

void processDevice( ... )
{
    int err;
    auto dev_handle = open_keyboard_device2("foo", &err );
    // set_keyboard_indicator2( dev_handle, KEYBOARD_CAPS_LOCK_ON );
    // ...
    writeln("退出processDevice");
}

void main() {
    processDevice();
    writeln("退出主");
}
posted @   zjh6  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示