View Single Post
  #3  
Old 06-07-2024, 19:56
WhoCares's Avatar
WhoCares WhoCares is offline
who cares
 
Join Date: Jan 2002
Location: Here
Posts: 468
Rept. Given: 11
Rept. Rcvd 32 Times in 25 Posts
Thanks Given: 69
Thanks Rcvd at 247 Times in 94 Posts
WhoCares Reputation: 32
Yes. I have done that for Windows native RPC handles.

The problem is, we have to specify the custom deleter each time when we declare a new variable. It's tedious. Maybe a typedef or "using"?
And, std::unique_ptr lacks abstraction for a default_value.

Also, we can add custom conversion operator for UniqueResource to avoid explicitly using
Get() method each time, just like "operator LPCSTR()", and "operator LPCWSTR()" of the ancient CString class from Microsoft.

Code:
    explicit operator ResourceType() const noexcept
    {
        return resource_;
    }
"explicit" can be omitted if you prefer convenience to safety.

samples of custom deleters for windows native RPC( "pointer" is defined for each functor):
Code:
struct StringBindingDeleter {
  typedef RPC_WSTR pointer;
  void operator()(RPC_WSTR stringBinding) {
    [[maybe_unused]] RPC_STATUS status = RpcStringFree(&stringBinding);
    assert(status == RPC_S_OK);
  }
};

struct RpcBindingDeleter {
  typedef RPC_BINDING_HANDLE pointer;
  void operator()(RPC_BINDING_HANDLE h) {
    [[maybe_unused]] RPC_STATUS status = RpcBindingFree(&h);
    assert(status == RPC_S_OK);
  }
};

usage:
Code:
  RPC_WSTR stringBinding = nullptr;
  status = RpcStringBindingCompose(nullptr, (RPC_WSTR)L"ncalrpc", nullptr,
                                   (RPC_WSTR)L"9038a9dd-b0f3-4745-827e-d4109e662cea", nullptr,
                                   (RPC_WSTR *)&stringBinding);
  if (status != RPC_S_OK || !stringBinding)
    return E_FAIL;

  std::unique_ptr stringBindingOwner(stringBinding, StringBindingDeleter);

  RPC_BINDING_HANDLE rpcBinding = nullptr;
  status = RpcBindingFromStringBinding(stringBinding, &rpcBinding);
  if (status != RPC_S_OK)
    return E_FAIL;

  std::unique_ptr rpcBindingOwner(rpcBinding, RpcBindingDeleter);
Quote:
Originally Posted by atom0s View Post
You can also do something similar to this by using the built-in 'std::shared_ptr' type. It allows for initialization with a custom deleter function. With that, you can pass a type cleanup call for types that have one. (You can also just define your own callback to cleanup custom/more unique types as needed.)

For example, using a 'HANDLE' type, which is cleaned up using 'CloseHandle':

Code:
const std::shared_ptr handle(::OpenProcess(PROCESS_VM_READ, FALSE, pid), ::CloseHandle);
Usage is then similar to your setup by just using 'handle.get()' to obtain the actual handle.
__________________
AKA Solomon/blowfish.

Last edited by WhoCares; 06-07-2024 at 22:28.
Reply With Quote
The Following 2 Users Say Thank You to WhoCares For This Useful Post:
SofTw0rm (06-11-2024), tonyweb (06-08-2024)