Pointers 将句柄变量传递给C++/CLI 我试图包装一个非托管C++ DLL,它与C++或CLI中的视频捕获卡对话,所以我可以引用我所拥有的C项目的函数。由于我不熟悉c++/cli语法,因此第一次包装调用无法正常工作。这是我的

Pointers 将句柄变量传递给C++/CLI 我试图包装一个非托管C++ DLL,它与C++或CLI中的视频捕获卡对话,所以我可以引用我所拥有的C项目的函数。由于我不熟悉c++/cli语法,因此第一次包装调用无法正常工作。这是我的,pointers,c++-cli,unmanaged,wrapper,handle,Pointers,C++ Cli,Unmanaged,Wrapper,Handle,这是我试图包装的函数declataion __declspec(dllimport) BOOL AZ_DeviceCreate(HANDLE& hLiveEvent, DWORD* hEncoderEvent, DWORD* pdwEncoderAddress, HANDLE& hAudioEvent, DWORD& dwAudioAddress); 这是我的c++/cli.h文件 namespace CaptureLibrary { public ref c

这是我试图包装的函数declataion

__declspec(dllimport) BOOL AZ_DeviceCreate(HANDLE& hLiveEvent, DWORD* hEncoderEvent, DWORD* pdwEncoderAddress, HANDLE& hAudioEvent, DWORD& dwAudioAddress);
这是我的c++/cli.h文件

namespace CaptureLibrary 
{
    public ref class CaptureCard
    {
    public:
        HANDLE m_hLiveEvent;
        DWORD *m_hEncoderEvent;
        HANDLE m_hAudioEvent;

    public:
        CaptureCard();
        bool CreateDevice();
        void DisposeDevice();
    };
}
还有我的.cpp

namespace CaptureLibrary
{
    CaptureCard::CaptureCard()
    {
        m_hLiveEvent = INVALID_HANDLE_VALUE;

        m_hEncoderEvent = new DWORD[MAX_VIDEO_CHANNEL];
        for (BYTE i=0;i<MAX_VIDEO_CHANNEL;i++)
        {
            m_hEncoderEvent[i] = (DWORD)INVALID_HANDLE_VALUE;
        }

        m_hAudioEvent = INVALID_HANDLE_VALUE;
    }

    bool CaptureCard::CreateDevice()
    {
        DWORD dwEncoderBuff[MAX_VIDEO_CHANNEL];
        DWORD dwACaptureBuffer = 0;

        if(AZ_DeviceCreate(m_hLiveEvent, m_hEncoderEvent, dwEncoderBuff, m_hAudioEvent, dwACaptureBuffer)==FALSE)
        {
            return false;
        }

        return true;
    }

    void CaptureCard::DisposeDevice()
    {
        AZ_DeviceClose();
    }
}
名称空间捕获库
{
CaptureCard::CaptureCard()
{
m_hLiveEvent=无效的\u句柄\u值;
m_hEncoderEvent=新DWORD[最大视频频道];

对于(BYTE i=0;i我的意思是建设性的:你走错了路。你在C++/CLI中的目标是以一种在.NET中看起来不陌生的方式包装非托管库,但你的
CaptureCard
类却没有这样做

  • 不公开字段,公开属性(我假设它们应该只为
    CaptureCard
    的成员获取)
  • 不要公开原始指针类型(例如
    HANDLE
    ),公开
    IntPtr
  • 不要公开原始C数组(例如,
    DWORD*
    )、公开
    array^
    ReadOnlyCollection^
    、或
    IEnumerable^
    (但不要公开
    array^
    通过属性、仅通过方法+
    array::Copy
    )只读的
  • 不仅要公开一个
    DisposeDevice
    方法,还要让类实际实现
    IDisposable
    ,这样就可以使用
    语句关闭设备,而不是强制使用
    try..finally
  • 由于类控制非托管资源,因此它需要一个终结器
.h

namespace CaptureLibrary 
{
    public ref class CaptureCard sealed
    {
    public:
        CaptureCard();
        ~CaptureCard();
        !CaptureCard();

        property IntPtr LiveEvent { IntPtr get(); }
        property IEnumerable<DWORD>^ EncoderEvent { IEnumerable<DWORD>^ get(); }
        property IntPtr AudioEvent { IntPtr get(); }

        bool CreateDevice();
        void DisposeDevice();

    private:
        bool m_bOpened;
        IntPtr m_hLiveEvent;
        array<DWORD>^ m_hEncoderEvent;
        IntPtr m_hAudioEvent;
    };
}
namespace CaptureLibrary
{
    CaptureCard::CaptureCard()
      : m_hLiveEvent(INVALID_HANDLE_VALUE),
        m_hEncoderEvent(gcnew array<DWORD>(MAX_VIDEO_CHANNEL)),
        m_hAudioEvent(INVALID_HANDLE_VALUE)
    {
        for (int i = 0, i_max = m_hEncoderEvent->Length; i != i_max; ++i)
            m_hEncoderEvent[i] = reinterpret_cast<DWORD>(INVALID_HANDLE_VALUE);
    }

    CaptureCard::~CaptureCard()
    {
        this->!CaptureCard();
    }

    CaptureCard::!CaptureCard()
    {
        DisposeDevice();
    }

    IntPtr CaptureCard::LiveEvent::get()
    {
        return m_hLiveEvent;
    }

    IEnumerable<DWORD>^ CaptureCard::EncoderEvent::get()
    {
        return m_hEncoderEvent;
    }

    IntPtr CaptureCard::AudioEvent::get()
    {
        return m_hAudioEvent;
    }

    bool CaptureCard::CreateDevice()
    {
        DisposeDevice();

        DWORD dwAudioAddress = 0u;
        DWORD dwEncoderAddress[MAX_VIDEO_CHANNEL];

        HANDLE hLiveEvent = m_hLiveEvent.ToPointer();
        HANDLE hAudioEvent = m_hAudioEvent.ToPointer();
        {
            pin_ptr<DWORD> hEncoderEvent = &m_hEncoderEvent[0];
            m_bOpened = AZ_DeviceCreate(hLiveEvent, hEncoderEvent, dwEncoderAddress, hAudioEvent, dwAudioAddress) == TRUE;
        }
        m_hLiveEvent = IntPtr(hLiveEvent);
        m_hAudioEvent = IntPtr(hAudioEvent);

        return m_bOpened;
    }

    void CaptureCard::DisposeDevice()
    {
        if (m_bOpened)
        {
            AZ_DeviceClose();
            m_bOpened = false;
        }
    }
}
名称空间捕获库
{
公共参考类CaptureCard已密封
{
公众:
CaptureCard();
~CaptureCard();
!CaptureCard();
属性IntPtr LiveEvent{IntPtr get();}
属性IEnumerable^EncoderEvent{IEnumerable^get();}
属性IntPtr AudioEvent{IntPtr get();}
bool-CreateDevice();
无效处分权();
私人:
布尔姆博佩内德;
IntPtr m_hLiveEvent;
数组^m_hEncoderEvent;
IntPtr m_hAudioEvent;
};
}
.cpp

namespace CaptureLibrary 
{
    public ref class CaptureCard sealed
    {
    public:
        CaptureCard();
        ~CaptureCard();
        !CaptureCard();

        property IntPtr LiveEvent { IntPtr get(); }
        property IEnumerable<DWORD>^ EncoderEvent { IEnumerable<DWORD>^ get(); }
        property IntPtr AudioEvent { IntPtr get(); }

        bool CreateDevice();
        void DisposeDevice();

    private:
        bool m_bOpened;
        IntPtr m_hLiveEvent;
        array<DWORD>^ m_hEncoderEvent;
        IntPtr m_hAudioEvent;
    };
}
namespace CaptureLibrary
{
    CaptureCard::CaptureCard()
      : m_hLiveEvent(INVALID_HANDLE_VALUE),
        m_hEncoderEvent(gcnew array<DWORD>(MAX_VIDEO_CHANNEL)),
        m_hAudioEvent(INVALID_HANDLE_VALUE)
    {
        for (int i = 0, i_max = m_hEncoderEvent->Length; i != i_max; ++i)
            m_hEncoderEvent[i] = reinterpret_cast<DWORD>(INVALID_HANDLE_VALUE);
    }

    CaptureCard::~CaptureCard()
    {
        this->!CaptureCard();
    }

    CaptureCard::!CaptureCard()
    {
        DisposeDevice();
    }

    IntPtr CaptureCard::LiveEvent::get()
    {
        return m_hLiveEvent;
    }

    IEnumerable<DWORD>^ CaptureCard::EncoderEvent::get()
    {
        return m_hEncoderEvent;
    }

    IntPtr CaptureCard::AudioEvent::get()
    {
        return m_hAudioEvent;
    }

    bool CaptureCard::CreateDevice()
    {
        DisposeDevice();

        DWORD dwAudioAddress = 0u;
        DWORD dwEncoderAddress[MAX_VIDEO_CHANNEL];

        HANDLE hLiveEvent = m_hLiveEvent.ToPointer();
        HANDLE hAudioEvent = m_hAudioEvent.ToPointer();
        {
            pin_ptr<DWORD> hEncoderEvent = &m_hEncoderEvent[0];
            m_bOpened = AZ_DeviceCreate(hLiveEvent, hEncoderEvent, dwEncoderAddress, hAudioEvent, dwAudioAddress) == TRUE;
        }
        m_hLiveEvent = IntPtr(hLiveEvent);
        m_hAudioEvent = IntPtr(hAudioEvent);

        return m_bOpened;
    }

    void CaptureCard::DisposeDevice()
    {
        if (m_bOpened)
        {
            AZ_DeviceClose();
            m_bOpened = false;
        }
    }
}
名称空间捕获库
{
CaptureCard::CaptureCard()
:m_hLiveEvent(无效的\u句柄\u值),
m_hEncoderEvent(gcnew阵列(最大视频通道)),
m\u hAudioEvent(无效的\u句柄\u值)
{
对于(int i=0,i_max=m_hEncoderEvent->Length;i!=i_max;++i)
m_hEncoderEvent[i]=重新解释\u强制转换(无效的\u句柄\u值);
}
CaptureCard::~CaptureCard()
{
此->!CaptureCard();
}
CaptureCard::!CaptureCard()
{
处置设备();
}
IntPtr CaptureCard::LiveEvent::get()
{
返回m_hLiveEvent;
}
IEnumerable^CaptureCard::EncoderEvent::get()
{
返回m_hEncoderEvent;
}
IntPtr CaptureCard::AudioEvent::get()
{
返回m_Haudio事件;
}
bool CaptureCard::CreateDevice()
{
处置设备();
DWORD DWAUDIONADDRESS=0u;
DWORD dwEncoderAddress[最大视频频道];
HANDLE hLiveEvent=m_hLiveEvent.ToPointer();
HANDLE hAudioEvent=m_hAudioEvent.ToPointer();
{
pin_ptr hEncoderEvent=&m_hEncoderEvent[0];
m_bOpened=AZ_DeviceCreate(hLiveEvent、hEncoderEvent、dwEncoderAddress、hAudioEvent、dwAudioAddress)=真;
}
m_hLiveEvent=IntPtr(hLiveEvent);
m_hAudioEvent=IntPtr(hAudioEvent);
返回已打开的m_;
}
作废CaptureCard::DisposedDevice()
{
如果(m_bOpened)
{
AZ_DeviceClose();
m_bOpened=假;
}
}
}

进一步改进的建议:

  • 完全摆脱
    CreateDevice
    DisposeDevice
    。这段代码有一种非常C-ish的心态。网络用户希望构造的对象有一个有意义的值,而无需调用单独的初始化函数,因此假设
    azu DeviceCreate
    预计不会定期失败,那么
    CreateDevice
    类的逻辑应该在类的构造函数中直接进行,失败时应该抛出异常
  • 如果多次调用
    AZ_DeviceClose
    是无害的,那么就彻底摆脱
    m_bOpened

我的意思是建设性的:你走错了路。你使用C++/CLI的目标是以一种在.NET中看起来不陌生的方式包装非托管库,但是你的
CaptureCard
类没有这样做

  • 不公开字段,公开属性(我假设它们应该只为
    CaptureCard
    的成员获取)
  • 不要公开原始指针类型(例如
    HANDLE
    ),公开
    IntPtr
  • 不要公开原始C数组(例如,
    DWORD*
    )、公开
    array^
    ReadOnlyCollection^
    、或
    IEnumerable^
    (但不要公开
    array^
    通过属性、仅通过方法+
    array::Copy
    )只读的
  • 不仅要公开一个
    DisposeDevice
    方法,还要让类实际实现
    IDisposable
    ,这样就可以使用
    语句关闭设备,而不是强制使用
    try..finally
  • 由于类控制非托管资源,因此它需要一个终结器
.h

namespace CaptureLibrary 
{
    public ref class CaptureCard sealed
    {
    public:
        CaptureCard();
        ~CaptureCard();
        !CaptureCard();

        property IntPtr LiveEvent { IntPtr get(); }
        property IEnumerable<DWORD>^ EncoderEvent { IEnumerable<DWORD>^ get(); }
        property IntPtr AudioEvent { IntPtr get(); }

        bool CreateDevice();
        void DisposeDevice();

    private:
        bool m_bOpened;
        IntPtr m_hLiveEvent;
        array<DWORD>^ m_hEncoderEvent;
        IntPtr m_hAudioEvent;
    };
}
namespace CaptureLibrary
{
    CaptureCard::CaptureCard()
      : m_hLiveEvent(INVALID_HANDLE_VALUE),
        m_hEncoderEvent(gcnew array<DWORD>(MAX_VIDEO_CHANNEL)),
        m_hAudioEvent(INVALID_HANDLE_VALUE)
    {
        for (int i = 0, i_max = m_hEncoderEvent->Length; i != i_max; ++i)
            m_hEncoderEvent[i] = reinterpret_cast<DWORD>(INVALID_HANDLE_VALUE);
    }

    CaptureCard::~CaptureCard()
    {
        this->!CaptureCard();
    }

    CaptureCard::!CaptureCard()
    {
        DisposeDevice();
    }

    IntPtr CaptureCard::LiveEvent::get()
    {
        return m_hLiveEvent;
    }

    IEnumerable<DWORD>^ CaptureCard::EncoderEvent::get()
    {
        return m_hEncoderEvent;
    }

    IntPtr CaptureCard::AudioEvent::get()
    {
        return m_hAudioEvent;
    }

    bool CaptureCard::CreateDevice()
    {
        DisposeDevice();

        DWORD dwAudioAddress = 0u;
        DWORD dwEncoderAddress[MAX_VIDEO_CHANNEL];

        HANDLE hLiveEvent = m_hLiveEvent.ToPointer();
        HANDLE hAudioEvent = m_hAudioEvent.ToPointer();
        {
            pin_ptr<DWORD> hEncoderEvent = &m_hEncoderEvent[0];
            m_bOpened = AZ_DeviceCreate(hLiveEvent, hEncoderEvent, dwEncoderAddress, hAudioEvent, dwAudioAddress) == TRUE;
        }
        m_hLiveEvent = IntPtr(hLiveEvent);
        m_hAudioEvent = IntPtr(hAudioEvent);

        return m_bOpened;
    }

    void CaptureCard::DisposeDevice()
    {
        if (m_bOpened)
        {
            AZ_DeviceClose();
            m_bOpened = false;
        }
    }
}
名称空间捕获库
{
公共参考类CaptureCard已密封
{
公众:
CaptureCard();
~CaptureCard();
!CaptureCard();
属性IntPtr LiveEvent{IntPtr get();}
属性IEnumerable^EncoderEvent{IEnumerable^get();}
属性IntPtr AudioEvent{IntPtr get();}
bool-CreateDevice();
无效处分权();
私人:
布尔姆博佩内德;