简体   繁体   English

使用中介 function 将回调定向到会员 function

[英]Using an intermediary function to direct a callback to a member function

I believe this question resembles this question .我相信这个问题类似于这个问题 However I am not sure how to adjust that to my case.但是我不确定如何根据我的情况进行调整。 Here is what I am doing.这就是我在做什么。

I currently have something like this我目前有这样的东西

void IOCompletionCallback(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped)
{
   ......    
}

void foo::Work()
{
     if (!BindIoCompletionCallback(hnd, IOCompletionCallback, 0))
     {
          printf("Error (error code: %u)\n", GetLastError());
     }
}

In the above code I am using the windows API BindIoCompletionCallback which takes in the function IOCompletionCallback .在上面的代码中,我使用的是 windows API BindIoCompletionCallback ,它接受 function IOCompletionCallback What I would like to do is to actually make IOCompletionCallback a method of foo instead of a free function so I could do this我想做的是实际上使IOCompletionCallback成为 foo 的方法而不是免费的 function 所以我可以这样做

if (!BindIoCompletionCallback(hnd, std::bind( &foo::IOCompletionCallback,this), 0))
{
}

but I read that is impossible because signature of the method takes in a specific type.但我读到这是不可能的,因为该方法的签名采用特定类型。 From the link I posted that it states that you can use an intermediary method.从我发布的链接中可以看出,您可以使用中介方法。 I am not sure how Ill be able to pass the instance address to that intermediary method.我不确定我如何能够将实例地址传递给该中间方法。 Any suggestions on that approach would be appreciated.对这种方法的任何建议将不胜感激。

Use the lpoverlapped you create and pass in to the io operation to store the calllback.使用您创建并传递给 io 操作的 lpoverlapped 来存储回调。 Well, data before/after ithe OVERLAPPED.. This function should just cast the overlapped to the larger state, find the callback you stored there, and invoke that callback.嗯,重叠之前/之后的数据。这个 function 应该只是将重叠转换为更大的 state,找到你存储在那里的回调,并调用那个回调。

The callback can be a std function with all of its wonderful utility.回调可以是 std function 及其所有出色的实用程序。

template<class D>
struct MyOverlapped:OVERLAPPED{
  std::function<void(DWORD, DWORD, D*)> callback;
  MyOverlapped():OVERLAPPED{0}{}
  virtual ~MyOverlapped() {}
};

Something sort of like this.有点像这样。 You'd use it like:你会像这样使用它:

template<class D>
void MyIOCompletionCallback(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped)
{
  if (!lpOverlapped) return;
  auto* pOverlapped = static_cast<D*>(lpOverlapped);
  pOverlapped->callback( dwErrorCode, dwNumberOfBytesTransferred, pOverlapped );
  delete pOverlapped; // as MyOverlapped
}

struct ReadFileOverlapped: MyOverlapped<ReadFileOverlapped> {
  explicit ReadFileOverlapped(std::size_t count = 0) {
    data.resize(count);
  }
  DWORD size() const { return static_cast<DWORD>(data.size()); }
  std::vector<std::byte> data;
};
auto overlapped = std::make_unique<ReadFileOverlapped>(1024);
overlapped->callback = [=](_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, ReadFileOverlapped* pOverlapped ) {
  std::cout << "Error " << dwErrorCode << "\n";
  std::cout << "Bytes " << dwNumberOfBytesTransfered << "\n";
  // get at data in pOverlapped->data.data() through pOverlapped->data.data()+dwNumberOfBytesTransfered or somesuch
};
if (ReadFile( hnd,
  overlapped->data.data(),
  overlapped->size(),
  nullptr,
  overlapped.get()
)) {
  if (BindIoCompletionCallback(hnd, MyIOCompletionCallback<ReadFileOverlapped>, 0))
  {
    overlapped.release();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM