栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Windows编程工作总结1-基础

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Windows编程工作总结1-基础

windows内核对象 windows下关闭句柄(HANDLE) 如何关闭句柄?

参考<>,句柄在错误情况下返回无效的值NULL。所以,类似于指针释放,句柄关闭代码如下:

#include 
void main()
{
    //句柄初始化为NULL
    HANDLE testHandle = NULL;

    //创建并使用句柄的源码
    ......;

    //关闭句柄
    if (testHandle != NULL) {
        CloseHandle(testHandle);
        //关闭后设置为NULL
        testHandle = NULL;
    }
}
多次打开句柄的问题

在<>3.2.2介绍了关闭句柄,先做一个补充。

如果两次打开一个内核对象,只需要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加载,详见<>(第5版)。

64位Window下DLL目录

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注册。

注意一定要以管理员的身份注册,否则无法注册成功。

具体的注册的示例代码详见<>(潘爱民著)的3.6

使用系统调用DllRegisterServer()

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
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/928922.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号