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
Post a Comment