2015-04-14 339 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

非常感谢,德米特里,我现在工作了 –