传递一个HANDLE变量在C++/CLI
非托管的.dll我想换一个托管C++动态链接库会谈到视频采集卡在C++/CLI,所以我可以从我有一个C#项目中引用的功能。由于我是C++/cli语法的新手,因此无法使第一次打包的调用工作。这是我的。传递一个HANDLE变量在C++/CLI
这里是功能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();
}
}
当我编译这与所需的头,我得到这个错误:
error C2664:
'AZ_DeviceCreate'
: cannot convert parameter 1 from'HANDLE'
to'HANDLE &'
谁能帮助我,因为我知道这是一个愚蠢的语法,我做错了。
在此先感谢。
我的意思是建设性的:你关上出师不利。你用C++/CLI这里的目标是包装的非托管库,将似乎没有外国在.NET的方式,但你的CaptureCard
类没有做到这一点。
- 不要暴露领域,公开属性(我认为他们应该得到,只为
CaptureCard
的成员) - 不要暴露原始指针类型(例如
HANDLE
),暴露IntPtr
- 唐“T暴露生C-阵列(例如
DWORD*
),暴露array<T>^
,ReadOnlyCollection<T>^
,或IEnumerable<T>^
(但不暴露array<T>^
意欲的待只读通过属性,仅通过方法+Array::Copy
) - 不要只暴露一个
DisposeDevice
方法,也使课堂真正实现IDisposable
因此该设备可以用using
声明被关闭而不是强制使用的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;
};
}
的.cpp:
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;
}
}
}
建议进一步改进:
- 获得完全摆脱
CreateDevice
和DisposeDevice
。这个代码有一个非常C - ish的心态; 。NET用户希望一个构造对象具有一个有意义的值,而不需要调用一个单独的初始化函数,所以假设AZ_DeviceCreate
不会定期失败,那么CreateDevice
的逻辑应该在类的构造函数中直接执行,并且应该在失败时引发异常 - 如果在调用
AZ_DeviceClose
多次是无害的,然后摆脱m_bOpened
完全
这里的问题是,你试图通过m_hLiveHandle为基准(即HANDLE &),但是这将需要m_hLiveHandle可以指出由一个本地指针(即它将被保证不在内存中移动)。但是,m_hLiveHandle是类(CaptureCard)的成员,意味着它的实例存储在托管堆上。这又意味着CaptureCard的实例可以在内存中移动(通过垃圾收集操作)。所以,如果你想使用m_hLiveHandle作为指针参数或引用参数,你必须使用pin_ptr来告诉垃圾收集器在调用本地方法的持续时间内不要移动这个对象。在这里阅读更多: http://msdn.microsoft.com/en-us/library/1dz8byfh(v=vs.80).aspx
哇,这是一个巨大的帮助!感谢您的帮助。这真的让我可以说话了。再一次,谢谢! – 2011-05-12 14:49:32