COM服务器作为windows服务,不能将数组作为函数参数传递

COM server as windows service, cannot pass array as function argument

本文关键字:数组 函数 不能 参数传递 服务 服务器 windows COM      更新时间:2023-10-16

我正在实现COM服务器(使用ATL)作为Windows服务。我在service header中定义了以下方法:

STDMETHOD(SetBytes)(long lenSource, const BYTE* pSource, VARIANT_BOOL *pResult);

这个方法在IDL文件中声明:

[
object,
uuid(351C5A5F-3EB8-4CC5-AB79-6DCD27C2F7E0),
dual,
pointer_default(unique)
]
interface ISampleInterface: IUnknown {
  HRESULT SetBytes([in] long lenSource, [in,ref,size_is(lenSource)] const BYTE* pSource, [out,retval] VARIANT_BOOL *pResult);
};

我从我的测试应用程序中调用它,像这样:

CoInitialize(NULL);
IUnknownPtr unknown_ptr;
HRESULT hr = unknown_ptr.CreateInstance(__uuidof(MyLib::SampleManager));
if (FAILED(hr)) {
  ...
};
MyLib::ISampleInterfacePtr sample_ptr;
sample_ptr = unknown_ptr; // no check here, assume sample_ptr is not null
VARIANT_BOOL function_result = VARIANT_FALSE;
vector<uint8_t> flash_data(1000, 2);
function_result = sample_ptr->SetBytes(flash_data.size(), &flash_data[0]);

我正在注册服务,执行:

MyService.exe /regserver
MyService.exe -service

然后我一步一步执行测试代码。当我要打开一个文件时,我们可以看到下面的

HRESULT _hr = raw_SetBytes(lenSource, pSource, &_result);

pSource绝对没问题,并且指向包含我的数据的内存区域。但是当我走得更远(我连接到服务与调试器),我在服务的函数SetBytes,只有一个字节从这个数组包含在内存区域,这个指针指向不同的地址。

我已经尝试通过dll实现服务器(它在系统中注册了regsvr32 [dllname]),指针在这种情况下是绝对ok的,所有的长度都传递了,不仅仅是一个字节。

我是COM技术的新手,想知道我错在哪里。

您可以将BYTE数组包装成SAFEARRAY。

       STDMETHODIMP MyClass::getVariantFromCharArray( char *inputCharArray, UINT inputCharArrayLength, VARIANT *outputVariant)
      {
          SAFEARRAYBOUND saBound;
          char  *pData = NULL;
          saBound.cElements = inputCharArrayLength;
           saBound.lLbound      = 0;
          VariantInit( outputVariant);
          (*outputVariant).vt = VT_UI1 | VT_ARRAY;
          (*outputVariant).parray = SafeArrayCreate( VT_UI1, 1, &saBound);
          if ( (*outputVariant).parray)
          {
             SafeArrayAccessData( (*outputVariant).parray, (void **)&pData);
        memcpy( pData, inputCharArray, inputCharArrayLength);
        SafeArrayUnaccessData( (*outputVariant).parray);    
        return S_OK;
    }
    else
    {
        return E_OUTOFMEMORY;
    }
}

您需要使用SAFEARRAY在COM中传递字节数组。