Unity3D C#建立COM介面

foenix66發表於2020-09-25

從CLSID建立COM介面需要從GUID獲得型別Type,然後通過Activator.CreateInstance建立介面物件。程式碼如下:

  Guid guid = new Guid("{3D2F839E-1186-4FCE-B772-B61FAE1ACED7}");
  try
  {
    filter = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(guid));
  }
  catch(Exception E)
  {
    print(E.Message);
  }

實際執行時,Type.GetTypeFromCLSID會丟擲異常:

The requested feature is not implemented.

說明該函式在mono平臺沒有實現。
為了解決這個問題,我們現在用的辦法是通過C++包裝COM介面,然後通過DLL暴露COM介面,供Unity3D C#使用。

// VCamDll.cpp : Defines the entry point for the DLL application.
//
# include <dshow.h>
# include <comdef.h>

# pragma comment(lib,"strmiids.lib")

// VCam filter interface
#pragma warning(disable : 4192)
#import  "VCamRenderer.tlb" no_namespace, raw_interfaces_only exclude("UINT_PTR") 
#include "VCamRenderer_i.c"

_COM_SMARTPTR_TYPEDEF(IBaseFilter, IID_IBaseFilter);
IBaseFilterPtr      g_pRenderer;
IVCamRenderer*    	g_pVCamRenderer;
template < typename T >
  void SAFE_RELEASE(T *&p)
{
  if (0 != p) {
    p->Release();
    p = NULL;
  }
}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
  return TRUE;
}
extern "C" __declspec(dllexport)
bool InitVCamSDK()
{
  HRESULT hr = CoCreateInstance(CLSID_VCamRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, reinterpret_cast<void**>(&g_pRenderer));
  if (FAILED(hr)) {
    return FALSE;
  }
  hr = g_pRenderer->QueryInterface(IID_IVCamRenderer, reinterpret_cast<void**>(&g_pVCamRenderer));
  if (FAILED(hr)) {
    return FALSE;
  }
  g_pVCamRenderer->SetLicenseCode(::SysAllocString(L"E9CT4-HE3C6-M7F5B-K97EP-DA5B3"));
  g_pVCamRenderer->SetOutputFormat(640, 480, 60, 0, 0);

  return true;
}
extern "C" __declspec(dllexport)
void UninitVCamSDK()
{
  SAFE_RELEASE(g_pVCamRenderer);
}
extern "C" __declspec(dllexport)
HRESULT SetCurrentDevice(BSTR friendly_name)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetCurrentDevice(friendly_name);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetOutputFormat(long width, long height, long fps, long format, long one_size_only)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetOutputFormat(width, height, fps, format, one_size_only);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT GetOutputFormat(long * width, long * height, long * fps, long * format, long * one_size_only)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->GetOutputFormat(width, height, fps, format, one_size_only);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetFillMode(long fill_mode)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetFillMode(fill_mode);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT GetFillMode(long * fill_mode)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->GetFillMode(fill_mode);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetMirror(long mirror)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetMirror(mirror);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetFlip(long flip)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetFlip(flip);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetRotateRight(long rotate)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetRotateRight(rotate);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SendFrame(unsigned char * i_rgb24_pixels, long i_width, long i_height, long i_stride)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SendFrame(i_rgb24_pixels, i_width, i_height, i_stride);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SendFrame32(unsigned char * i_rgb32_pixels, long i_width, long i_height, long i_stride)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SendFrame32(i_rgb32_pixels, i_width, i_height, i_stride);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SendFrameYUY2(unsigned char * i_yuy2, long i_width, long i_height, long i_stride)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SendFrameYUY2(i_yuy2, i_width, i_height, i_stride);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SendFrameNV12(unsigned char * i_nv12, long i_width, long i_height, long i_stride)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SendFrameNV12(i_nv12, i_width, i_height, i_stride);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SendFrameEx(VARIANT i_rgb24_array, long i_width, long i_height)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SendFrameEx(i_rgb24_array, i_width, i_height);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT CaptureScreen(long i_x, long i_y, long i_width, long i_height)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->CaptureScreen(i_x, i_y, i_width, i_height);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetConnectionNotificationEvent(__int64 i_handle)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetConnectionNotificationEvent(i_handle);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT GetConnectedCount(long * o_count)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->GetConnectedCount(o_count);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT IsOpened()
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->IsOpened();
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT Snapshot(BSTR filename)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->Snapshot(filename);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetIdleFileName(BSTR file_name)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetIdleFileName(file_name);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetFriendlyName(BSTR friendly_name)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetFriendlyName(friendly_name);
  }
  else {
    return S_FALSE;
  }
}
extern "C" __declspec(dllexport)
HRESULT SetLicenseCode(BSTR license_code)
{
  if (NULL != g_pVCamRenderer) {
    return g_pVCamRenderer->SetLicenseCode(license_code);
  }
  else {
    return S_FALSE;
  }
}

相關文章