2015-04-14 341 views
2

我有一個功能良好的C++ DLL,其中有8個被C#應用程序使用的方法。所有方法都有簡單的類型參數,如int*float*,用於將信息從C++代碼傳輸到C#代碼。C2259:'ATL :: CComObject <Base>':無法實例化抽象類

現在我擴大與具有參數char*的方法的接口,我從Visual Studion 2012得到下面的編譯錯誤:

錯誤C2259:「ATL :: CComObject」:不能實例化抽象類

我附加了C,H和IDL文件。方法GetError被添加並導致編譯錯誤。

在此先感謝您的評論。

Laser.h:

// Laser.h: Definition of the Laser class 
// 
////////////////////////////////////////////////////////////////////// 

#if !defined(AFX_LASER_H__78A65319_A610_4974_86E6_F04496ADA33F__INCLUDED_) 
#define AFX_LASER_H__78A65319_A610_4974_86E6_F04496ADA33F__INCLUDED_ 

#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 

#include "resource.h"  // main symbols 
#include "ECLaserScanner.h" 

///////////////////////////////////////////////////////////////////////////// 
// Laser 

class Laser : 
    public IDispatchImpl<ILaser, &IID_ILaser, &LIBID_LASERSCANNERLib>, 
    public ISupportErrorInfo, 
    public CComObjectRoot, 
    public CComCoClass<Laser,&CLSID_Laser> 
{ 
public: 
    Laser() {} 
BEGIN_COM_MAP(Laser) 
    COM_INTERFACE_ENTRY(IDispatch) 
    COM_INTERFACE_ENTRY(ILaser) 
    COM_INTERFACE_ENTRY(ISupportErrorInfo) 
END_COM_MAP() 
//DECLARE_NOT_AGGREGATABLE(Laser) 
// Remove the comment from the line above if you don't want your object to 
// support aggregation. 

DECLARE_REGISTRY_RESOURCEID(IDR_Laser) 
// ISupportsErrorInfo 
    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid); 

// ILaser 
public: 
    STDMETHOD(Construct)(); 
    STDMETHOD(Destruct)(); 
    STDMETHOD(Scan)(int* nrOfPointsNS, int* nrOfPointsEW); 
    STDMETHOD(Setup)(int scanSet, int* error); 
    STDMETHOD(GetData)(int indexNS, int indexEW, float* pointNS, float* pointEW, float* height); 
    STDMETHOD(GetColor)(int indexNS, int indexEW, float* red, float* green, float* blue); 
    STDMETHOD(GetIntensity)(int indexNS, int indexEW, float* intensity); 
    STDMETHOD(GetInfo)(float* temperature, float* supplyVoltage, int* operatingTime, int* laserTime, int* motorTime); 
    STDMETHOD(GetError)(char* error); 
}; 

#endif // !defined(AFX_LASER_H__78A65319_A610_4974_86E6_F04496ADA33F__INCLUDED_) 

Laser.cpp:

// Laser.cpp : Implementation of CLaserScannerApp and DLL registration. 

#include "stdafx.h" 
#include "LaserScanner.h" 
#include "Laser.h" 
///////////////////////////////////////////////////////////////////////////// 
// 
enum ScanSetIndexType 
{ 
    none, 
    dump1, 
    dump2, 
    dump3, 
    dump4, 
    dump5, 
    dump6, 
    dump7, 
    oven1, 
    oven2, 
    oven3, 
    oven4, 
    oven5, 
    bunker, 
    calibration 
}; 

ECLaserScanner* m_scanner = 0; 

STDMETHODIMP Laser::InterfaceSupportsErrorInfo(REFIID riid) 
{ 
    static const IID* arr[] = 
    { 
     &IID_ILaser, 
    }; 

    for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++) 
    { 
     if (InlineIsEqualGUID(*arr[i],riid)) 
      return S_OK; 
    } 
    return S_FALSE; 
} 

STDMETHODIMP Laser::Construct() 
{ 
    if (m_scanner) 
    { 
    Destruct(); 
    } 

    m_scanner = new ECLaserScanner(); 

    return S_OK; 
} 

STDMETHODIMP Laser::Destruct() 
{ 
    if (!m_scanner) 
    { 
    return -1; 
    } 

    delete m_scanner; 
    m_scanner = 0; 

    return S_OK; 
} 

STDMETHODIMP Laser::Setup(int set, int* error) 
{ 
    if (!m_scanner) 
    { 
    return -1; 
    } 

    ScanSetType scanSet; 
    ScanSetIndexType index = (ScanSetIndexType) set; 

    scanSet.m_id = set; 

    switch (index) 
    { 
    case calibration: 
     scanSet.m_startAngleNS = 100.0; 
     scanSet.m_deltaAngleNS = 0.2; 
     scanSet.m_deltaCountNS = 126; 
     scanSet.m_startAngleEW = 107.0; 
     scanSet.m_deltaAngleEW = 0.199; 
     scanSet.m_deltaCountEW = 69; 
     break; 
    case bunker: 
     scanSet.m_startAngleNS = 100.0; 
     scanSet.m_deltaAngleNS = 0.1; 
     scanSet.m_deltaCountNS = 1600; // ending at 260 degrees 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.2; 
     scanSet.m_deltaCountEW = 350; 
     break; 
    case oven1: 
     scanSet.m_startAngleNS = 225.0; 
     scanSet.m_deltaAngleNS = 0.2; 
     scanSet.m_deltaCountNS = 77; 
     scanSet.m_startAngleEW = 107.0; 
     scanSet.m_deltaAngleEW = 0.199; 
     scanSet.m_deltaCountEW = 68; 
     break; 
    case oven2: 
     scanSet.m_startAngleNS = 190.0; 
     scanSet.m_deltaAngleNS = 0.2; 
     scanSet.m_deltaCountNS = 126; 
     scanSet.m_startAngleEW = 115.0; 
     scanSet.m_deltaAngleEW = 0.199; 
     scanSet.m_deltaCountEW = 75; 
     break; 
    case oven3: 
     scanSet.m_startAngleNS = 145.0; 
     scanSet.m_deltaAngleNS = 0.2; 
     scanSet.m_deltaCountNS = 127; 
     scanSet.m_startAngleEW = 115.0; 
     scanSet.m_deltaAngleEW = 0.199; 
     scanSet.m_deltaCountEW = 75; 
     break; 
    case oven4: 
     scanSet.m_startAngleNS = 110.0; 
     scanSet.m_deltaAngleNS = 0.2; 
     scanSet.m_deltaCountNS = 126; 
     scanSet.m_startAngleEW = 107.0; 
     scanSet.m_deltaAngleEW = 0.199; 
     scanSet.m_deltaCountEW = 69; 
     break; 
    case oven5: 
     scanSet.m_startAngleNS = 110.0; // was voor geheel oven 4 de startAngleNS 
     scanSet.m_deltaAngleNS = 0.2; 
     scanSet.m_deltaCountNS = 90; 
     scanSet.m_startAngleEW = 107.0; 
     scanSet.m_deltaAngleEW = 0.199; 
     scanSet.m_deltaCountEW = 69; 
     break; 
     case dump1: 
     scanSet.m_startAngleNS = 180.0; 
     scanSet.m_deltaAngleNS = 0.0; 
     scanSet.m_deltaCountNS = 0; 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.0; 
     scanSet.m_deltaCountEW = 0; 
     break; 
    case dump2: 
     scanSet.m_startAngleNS = 180.0; 
     scanSet.m_deltaAngleNS = 0.0; 
     scanSet.m_deltaCountNS = 0; 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.0; 
     scanSet.m_deltaCountEW = 0; 
     break; 
    case dump3: 
     scanSet.m_startAngleNS = 180.0; 
     scanSet.m_deltaAngleNS = 0.0; 
     scanSet.m_deltaCountNS = 0; 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.0; 
     scanSet.m_deltaCountEW = 0; 
     break; 
    case dump4: 
     scanSet.m_startAngleNS = 180.0; 
     scanSet.m_deltaAngleNS = 0.0; 
     scanSet.m_deltaCountNS = 0; 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.0; 
     scanSet.m_deltaCountEW = 0; 
     break; 
    case dump5: 
     scanSet.m_startAngleNS = 180.0; 
     scanSet.m_deltaAngleNS = 0.0; 
     scanSet.m_deltaCountNS = 0; 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.0; 
     scanSet.m_deltaCountEW = 0; 
     break; 
    case dump6: 
     scanSet.m_startAngleNS = 180.0; 
     scanSet.m_deltaAngleNS = 0.0; 
     scanSet.m_deltaCountNS = 0; 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.0; 
     scanSet.m_deltaCountEW = 0; 
     break; 
    case dump7: 
     scanSet.m_startAngleNS = 180.0; 
     scanSet.m_deltaAngleNS = 0.0; 
     scanSet.m_deltaCountNS = 0; 
     scanSet.m_startAngleEW = 50.0; 
     scanSet.m_deltaAngleEW = 0.0; 
     scanSet.m_deltaCountEW = 0; 
     break; 
    default: 
     return -1; 
    } 

    *error = m_scanner->Setup(scanSet); 

    return S_OK; 
} 

STDMETHODIMP Laser::Scan(int* nrOfPointsNS, int* nrOfPointsEW) 
{ 
    if (!m_scanner) 
    { 
    return -1; 
    } 

    m_scanner->Scan(); 

    m_scanner->GetScanner()->GetDimension(nrOfPointsNS, nrOfPointsEW); 

    return S_OK; 
} 

STDMETHODIMP Laser::GetData(int indexNS, int indexEW, float* pointNS, float* pointEW, float* height) 
{ 
    if (!m_scanner) 
    { 
    return -1; 
    } 

    int result = m_scanner->GetData(indexNS, indexEW, pointNS, pointEW, height); 

    if (result != 0) 
    { 
    return result; 
    } 

    return S_OK; 
} 

STDMETHODIMP Laser::GetColor(int indexNS, int indexEW, float* red, float* green, float* blue) 
{ 
    if (!m_scanner) 
    { 
    return -1; 
    } 

    int result = m_scanner->GetColor(indexNS, indexEW, red, green, blue); 

    if (result != 0) 
    { 
    return result; 
    } 

    return S_OK; 
} 

STDMETHODIMP Laser::GetIntensity(int indexNS, int indexEW, float* intensity) 
{ 
    if (!m_scanner) 
    { 
    return -1; 
    } 

    int result = m_scanner->GetIntensity(indexNS, indexEW, intensity); 

    if (result != 0) 
    { 
    return result; 
    } 

    return S_OK; 
} 

STDMETHODIMP Laser::GetInfo(float* temperature, 
          float* supplyVoltage, 
          int* operatingTime, 
          int* laserTime, 
          int* motorTime) 
{ 
    if (!m_scanner) 
    { 
    return -1; 
    } 

    int result = m_scanner->GetInfo(temperature, supplyVoltage, operatingTime, laserTime, motorTime); 

    if (result != 0) 
    { 
    return result; 
    } 

    return S_OK; 
} 

STDMETHODIMP Laser::GetError(char* error) 
{ 
    error = "hallo"; 

    return S_OK; 
} 

** ** LaserScanner.idl

// LaserScanner.idl : IDL source for LaserScanner.dll 
// 

// This file will be processed by the MIDL tool to 
// produce the type library (LaserScanner.tlb) and marshalling code. 

import "oaidl.idl"; 
import "ocidl.idl"; 

    [ 
     object, 
     uuid(1C161160-B6B4-4AE2-BF07-A14D78AF6270), 
     dual, 
     helpstring("ILaser Interface"), 
     pointer_default(unique) 
    ] 
    interface ILaser : IDispatch 
    { 
     [id(1), helpstring("method Construct")] HRESULT Construct(); 
     [id(2), helpstring("method Destruct")] HRESULT Destruct(); 
     [id(3), helpstring("method Setup")] HRESULT Setup(int scanSet, int* errorz); 
     [id(4), helpstring("method Scan")] HRESULT Scan(int* nrOfPointsNS, int* nrOfPointsEW); 
     [id(5), helpstring("method GetData")] HRESULT GetData(int indexNS, int indexEW, float* pointNS, float* pointEW, float* height); 
     [id(6), helpstring("method GetColor")] HRESULT GetColor(int indexNS, int indexEW, float* red, float* green, float* blue); 
     [id(7), helpstring("method GetIntensity")] HRESULT GetIntensity(int indexNS, int indexEW, float* intensity); 
     [id(8), helpstring("method GetInfo")] HRESULT GetInfo(float* temperature, float* supplyVoltage, int* operatingTime, int* laserTime, int* motorTime); 
     [id(9), helpstring("method GetError")] HRESULT GetError(char* error); 
    }; 

[ 
    uuid(3B556F88-6FEC-4A55-A7A3-8360C9103056), 
    version(1.0), 
    helpstring("LaserScanner 1.4 Type Library") 
] 
library LASERSCANNERLib 
{ 
    importlib("stdole32.tlb"); 
    importlib("stdole2.tlb"); 


    [ 
     uuid(67927D42-6C28-466F-8D83-9346A0D48F71), 
     helpstring("Laser Class") 
    ] 
    coclass Laser 
    { 
     [default] interface ILaser; 
    }; 
}; 

回答

1

您應該使用BSTR字符串在COM中。或者您需要爲該類型的字符串創建custom marshaler

// .idl 
[id(9), helpstring("method GetError")] HRESULT GetError(BSTR* error); 

// .h 
STDMETHOD(GetError)(BSTR* error); 

// .cpp 
STDMETHODIMP Laser::GetError(BSTR* pError) 
{ 
    HRESULT hr = E_INVALIDARG; 
    CComBSTR e(L"some sort of error message"); 
    if (pError) { 
     hr = e.CopyTo(pError); 
    } 
    return hr; 
} 
+0

謝謝德米特里。我試過這個,但在C#中,我得到了一個「ref string」作爲來自封送處理器的參數,放在BSTR *中的文本沒有出現在引用的字符串中。對此有何建議? –

+0

您應該使用'SysAllocString()',或'ATL :: CComBSTR'或'_bstr_t'在'GetError()'中創建一個字符串,甚至是一個空字符串。在C#端你應該使用類似'string error; Laser.GetError(出錯);' –

+0

非常感謝,德米特里,我現在工作了 –