2011-05-11 267 views
1

非託管的.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 &'

誰能幫助我,因爲我知道這是一個愚蠢的語法,我做錯了。

在此先感謝。

回答

1

我的意思是建設性的:你關上出師不利。你用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; 
     } 
    } 
} 

建議進一步改進:

  • 獲得完全擺脫CreateDeviceDisposeDevice。這個代碼有一個非常C - ish的心態; 。NET用戶希望一個構造對象具有一個有意義的值,而不需要調用一個單獨的初始化函數,所以假設AZ_DeviceCreate不會定期失敗,那麼CreateDevice的邏輯應該在類的構造函數中直接執行,並且應該在失敗時引發異常
  • 如果在調用AZ_DeviceClose多次是無害的,然後擺脫m_bOpened完全
+0

哇,這是一個巨大的幫助!感謝您的幫助。這真的讓我可以說話了。再一次,謝謝! – 2011-05-12 14:49:32

0

這裏的問題是,你試圖通過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