【问题标题】:COM server as windows service, cannot pass array as function argumentCOM 服务器作为 Windows 服务,不能将数组作为函数参数传递
【发布时间】:2013-02-23 07:24:41
【问题描述】:

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

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

然后我一步一步地执行测试代码。当我要去 tli 文件时,我们可以看到以下内容

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

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

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

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

【问题讨论】:

  • 您的代理工作不正常,我看不出 MIDL 属性有问题。您从未提及注册它,请确保您没有使用错误属性构建的旧活动。
  • 你能指导我一下吗?我该怎么做才能检查它?我在哪里可以看到它?我注销了以前的服务([service_name] /unregserver),这就是我现在所知道的关于注册的全部信息......我想了解发生了什么,尽管 SAFEARRAYs 的情况非常好。

标签: c++ arrays windows service com


【解决方案1】:

您可以将 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;
    }
}

【讨论】:

  • 您不需要VARIANT 来使用SAFEARRAY,除非您需要支持OleAutomation 客户端,例如脚本环境
  • 是的,这是处理数组的好方法,谢谢大家!我现在没有支持脚本环境的任务,所以我会考虑现在是离开 VARIANT 还是使用 SAFEARRAY 更好。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 2013-05-17
    相关资源
    最近更新 更多