Pointers 将句柄变量传递给C++/CLI 我试图包装一个非托管C++ DLL,它与C++或CLI中的视频捕获卡对话,所以我可以引用我所拥有的C项目的函数。由于我不熟悉c++/cli语法,因此第一次包装调用无法正常工作。这是我的
这是我试图包装的函数declataionPointers 将句柄变量传递给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
__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();
无效处分权();
私人:
布尔姆博佩内德;