winapi - Using unique_ptr / shared_ptr with API functions returning resources as out parameters via pointer -


i’m catching c++ 11/14 stuff in current project. have trouble using unique_ptr/shared_ptr api functions returning resources out parameters via pointer.

let’s consider dsgetdcname(..., __out pdomain_controller_info* ppdci) example.

before c++11 there widespread pattern work windows apis. have riia class holds pdomain_controller_info, calls netapibufferfree in destructor, , has pdomain_controller_info* operator&() can write:

info_ptr spinfo; dsgetdcname(..., &spinfo); 

now c++ 11/14 see lot of articles advocating unique_ptr/shared_ptr custom deleter release resource in proper way. , works when resource returned r-value function (loadlibrary example of this).

one solution found attach raw-pointer smart pointer after api call:

pdomain_controller_info pdci = nullptr; dsgetdcname(..., &pdci); std::unique_ptr<domain_controller_info, decltype(&netapibufferfree)> spinfo(pdci, &netapibufferfree); 

however, not way like. far understand, new smart pointers not designed work out parameters because of ‘safty first’ approach.

can done here? perhaps kind of functor class serving out parameter proxy can write dsgetdcname(..., &out_param(spinfo)) ?

well, can make temporary wrapper initialize std::unique_ptr upon destruction:

#include <windows.h> #include <dsgetdc.h> #include <lm.h>  #include <memory>  template<typename t, typename d> struct outparameterwrapper {     outparameterwrapper(std::unique_ptr<t, d>& target) : m_target(target), m_psource(nullptr)     {     }     ~outparameterwrapper()     {         m_target.reset(m_psource);     }     operator t**()     {         return &m_psource;     }     std::unique_ptr<t, d>& m_target;     t* m_psource; };  int main(int argc, char** argv) {     std::unique_ptr<domain_controller_info, decltype(&netapibufferfree)> spinfo(nullptr, netapibufferfree);     dsgetdcname(null, null, null, null, 0, outparameterwrapper<domain_controller_info, decltype(&netapibufferfree)>(spinfo));     return 0; } 

edit

to have automatic deduction , have work both std::unique_ptr , std::shared_ptr can this:

#include <windows.h> #include <dsgetdc.h> #include <lm.h>  #pragma comment(lib, "netapi32.lib")  #include <memory>  template<typename t, typename p> struct outparameterwrapper {     outparameterwrapper(p& target) : m_target(target), m_psource(nullptr)     {     }     ~outparameterwrapper()     {         m_target.reset(m_psource);     }     operator t**()     {         return &m_psource;     }      p& m_target;     t* m_psource; };  template<typename p> outparameterwrapper<typename p::element_type, p> makeoutparameterwrapper(p& target) {     return outparameterwrapper<typename p::element_type,p>(target); }  int main(int argc, char** argv) {     std::unique_ptr<domain_controller_info, decltype(&netapibufferfree)> spinfo(nullptr, netapibufferfree);     std::shared_ptr<domain_controller_info> spinfo2(nullptr, netapibufferfree);     auto nresult = dsgetdcname(null, null, null, null, 0, makeoutparameterwrapper(spinfo));     dsgetdcname(null, null, null, null, 0, makeoutparameterwrapper(spinfo2));     return 0; } 

Comments

Popular posts from this blog

yii2 - Yii 2 Running a Cron in the basic template -

asp.net - 'System.Web.HttpContext' does not contain a definition for 'GetOwinContext' Mystery -

mercurial graft feature, can it copy? -