参考<
#include多次打开句柄的问题void main() { //句柄初始化为NULL HANDLE testHandle = NULL; //创建并使用句柄的源码 ......; //关闭句柄 if (testHandle != NULL) { CloseHandle(testHandle); //关闭后设置为NULL testHandle = NULL; } }
在<
如果两次打开一个内核对象,只需要CloseHandle()一次。具体代码如下。在MSDN上明确指出,不要CloseHandle()一个句柄两次。
#include#include #include using namespace std; int32_t main() { HANDLE testHandleA = nullptr; HANDLE testHandleB = nullptr; const int SHARED_MEM_SIZE = 4096; char szMemName[MAX_PATH]; int iDesktopNumber = -1; //GetDesktopNumber(); testHandleA = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, szMemName); if (!testHandleA) { testHandleA = CreateFileMappingA( (HANDLE)INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, SHARED_MEM_SIZE, szMemName); if (!testHandleA) cout <<"OpenFileMappingA failed"< 如果两次打开两个内核对象,需要CloseHandle()两次。
#include#include #include using namespace std; int32_t main() { HANDLE testHandleA = nullptr; HANDLE testHandleB = nullptr; const int SHARED_MEM_SIZE = 4096; char szMemName[MAX_PATH]; int iDesktopNumber = -1; //GetDesktopNumber(); testHandleA = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, szMemName); if (!testHandleA) { testHandleA = CreateFileMappingA( (HANDLE)INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, SHARED_MEM_SIZE, szMemName); if (!testHandleA) cout <<"OpenFileMappingA failed"< 多次关闭句柄将释放资源 所以如果句柄资源仍然要使用,不要将其释放。所以一般来说,初始化时创建一次,结束时关闭一次,中间多次打开和关闭。
Windows资源释放没有设置nullptr注意windows中的Release()仅仅是减少计数,释放资源而已,并没有将指针设置为nullptr。经过实际测试。所以在调用释放资源时,没有必要if(x!=nullptr),直接调用Release()即可。
DLL技术 加载dll在使用LoadLibraryA()加载DLL库时,出现126(十进制)的错误。显式原因是DLL找不到,隐式的原因是当前DLL依赖太多,无法搜索的到。
使LoadLibraryEx(“DLL绝对路径”, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);通过指定LOAD_WITH_ALTERED_SEARCH_PATH,让系统DLL搜索顺序从DLL所在目录开始。
关于DLL加载,详见<
64位Window下DLL目录>(第5版)。 C:WindowsSystem32:用于存放64位的dll。
C:WindowsSysWOW64:存放32位的DLL,使32位的dll运行在64位的系统中。全称为32bit Windows On 64bit Windows。
上面的结论经过了dumpbin的实测。
COM技术 资料详见https://blog.csdn.net/fly0413/article/details/114651812。
关于COM的书籍,比较古老,都已经搜集。最新的资料比如微软的官方资料: https://docs.microsoft.com/en-us/windows/win32/com/component-object-model–com–portal。
COM组件注册关于MSDN中COM组件的注册:https://docs.microsoft.com/en-us/windows/win32/com/registering-com-servers。下面以我们使用的两种方式。
使用regsvr32注册1、 以管理员的身份打开cmd。https://jingyan.baidu.com/article/ceb9fb10b53ab88cac2ba05b.html。右键屏幕左下角的开始菜单,选择windows powershell(管理员)即可。
2、 在cmd 打开regedit。
3、 右键HKEY_CLASSES_ROOT,点击权限设置。将权限设置为读写设置。
4、 采用regsvr32进行dll注册。
注意一定要以管理员的身份注册,否则无法注册成功。
具体的注册的示例代码详见<
使用系统调用DllRegisterServer()>(潘爱民著)的3.6 https://blog.csdn.net/hellokandy/article/details/78396037。
MSDN中的关键字为Self-Registration,具体为: https://docs.microsoft.com/en-us/windows/win32/com/self-registration。
ComPtr专用于COM的智能指针。比如用于DirectD3D9、DirectD3D11、DirectD3D12、DXGI的编程。
三个获取指针接口的区别。
- 微软官方资料: https://docs.microsoft.com/en-us/cpp/cppcx/wrl/comptr-class?view=msvc-170。
- Github上的资料为: https://github.com/Microsoft/DirectXTK/wiki/ComPtr。
ComPtr::GetAddressOf():获取指针的指针(T**)
ComPtr::ReleaseAndGetAddressOf():该方法相当于先调用Reset方法(调用Release,并将指针置null),再调用GetAddressOf方法获取T**,常用在COM组件接口的函数输出,适用于实例可能会被反复构造的情况下。
ComPtr::Get():该方法返回T*,常用在COM组件接口的函数输入。
windows中COM接口的实现其实现分为C和C++两个部分。其中C的实现展现了更多的底层细节,值的参考。以dxgi.h中的IDXGIObject为例说明。
//windows系统中,dxgi.h中IDXGIObject定义实现 EXTERN_C const IID IID_IDXGIObject; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("aec22fb8-76f3-4639-9be0-28eb43a67a2e") IDXGIObject : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetPrivateData( _In_ REFGUID Name, UINT DataSize, _In_reads_bytes_(DataSize) const void *pData) = 0; virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( _In_ REFGUID Name, _In_opt_ const IUnknown *pUnknown) = 0; virtual HRESULT STDMETHODCALLTYPE GetPrivateData( _In_ REFGUID Name, _Inout_ UINT *pDataSize, _Out_writes_bytes_(*pDataSize) void *pData) = 0; virtual HRESULT STDMETHODCALLTYPE GetParent( _In_ REFIID riid, _COM_Outptr_ void **ppParent) = 0; }; #else//C语言下接口的定义。 typedef struct IDXGIObjectVtbl { //C++中基类IUnknown接口的定义。 BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IDXGIObject * This, REFIID riid, _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IDXGIObject * This); ULONG ( STDMETHODCALLTYPE *Release )( IDXGIObject * This); //当前类的接口定义。 HRESULT ( STDMETHODCALLTYPE *SetPrivateData )( IDXGIObject * This, _In_ REFGUID Name, UINT DataSize, _In_reads_bytes_(DataSize) const void *pData); HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )( IDXGIObject * This, _In_ REFGUID Name, _In_opt_ const IUnknown *pUnknown); HRESULT ( STDMETHODCALLTYPE *GetPrivateData )( IDXGIObject * This, _In_ REFGUID Name, _Inout_ UINT *pDataSize, _Out_writes_bytes_(*pDataSize) void *pData); HRESULT ( STDMETHODCALLTYPE *GetParent )( IDXGIObject * This, _In_ REFIID riid, _COM_Outptr_ void **ppParent); END_INTERFACE } IDXGIObjectVtbl; interface IDXGIObject { CONST_VTBL struct IDXGIObjectVtbl *lpVtbl; }; ...... #endif



