haha0518 发表于 2024-9-9 12:31:01

C++ COM组件字符串数组的传递


在ATL下开发简单的COM组件很简单,唯一的难点在于复杂参数的传递。比如说字符串数组,需要学习SAFFARRAY,bstr以及VARIANT的用法。

下面贴出代码,展示一个字符串数组如何传递。

在COM组件的方法里面:
STDMETHODIMP CwordCountService::analyzeTheWordFile(BSTR filename, VARIANT* wordsSafearray, VARIANT* frequencySafearray)
{
      // TODO: 在此添加实现代码
      MYWORD **wordArray;
      int wordCount;
      char *cFilename = _com_util::ConvertBSTRToString(filename);
      //调用analyzeTxtWordFile函数对指定文档进行统计分析
      analyzeTxtWordFile(cFilename, &wordArray, &wordCount);
      delete cFilename;
      cFilename = nullptr;

      //把统计到的结果,存放到安全数组里面
      VARIANT var1, var2;
      VariantInit(&var1);
      VariantInit(&var2);
      var1.vt = VT_BSTR;
      var2.vt = VT_INT;
      SAFEARRAY *pArray1, *pArray2;
      pArray1 = SafeArrayCreateVector(VT_VARIANT, 0, wordCount);
      pArray2 = SafeArrayCreateVector(VT_VARIANT, 0, wordCount);
      for (long i = 0; i < wordCount; i++)
      {
                var1.bstrVal = _com_util::ConvertStringToBSTR(wordArray->MYWORD);
                var2.intVal = wordArray->count;
                SafeArrayPutElement(pArray1, &i, &var1);
                SafeArrayPutElement(pArray2, &i, &var2);
                free(wordArray);
      }
      free(wordArray);

      VariantClear(&var1);
      VariantClear(&var2);
      wordsSafearray->vt = VT_ARRAY | VT_VARIANT;
      frequencySafearray->vt = VT_ARRAY | VT_VARIANT;
      wordsSafearray->parray = pArray1;
      frequencySafearray->parray = pArray2;
      return S_OK;
}

调用COM组件的C++代码:
#include <atlbase.h>
#import "D:\wordCountComponent.dll" no_namespace

int main()
{
      //根据接口的clsid来初始化com组件
      CoInitialize(NULL);
      CLSID clsid;
      HRESULT hr = CLSIDFromString(OLESTR("{40F2E186-5636-4F0D-87AB-DF351B41D133}"), &clsid);

      //用智能指针去获取接口指针
      CComPtr<IwordCountService> wordCountServicePtr;
      hr = wordCountServicePtr.CoCreateInstance(clsid);
      if (NOERROR != hr)
      {
                printf("初始化com失败!\n");
                return -1;
      }

      VARIANT var1, var2;
      VariantInit(&var1);
      VariantInit(&var2);
      SAFEARRAY *pArray1, *pArray2;

      BSTR fileName = _com_util::ConvertStringToBSTR("d:/Romeo and Juliet.txt");
      //调用analyzeTheWordFile函数分析文件,分析得到的结果存放在var1, var2的安全数组中
      wordCountServicePtr->analyzeTheWordFile(fileName, &var1, &var2);
      ::SysFreeString(fileName);
      BSTR fileName2 = _com_util::ConvertStringToBSTR("d:/log.txt");
      //分析完之后,可以利用得到的结果,调用createTxtLogFile生成统计文件
      wordCountServicePtr->createTxtLogFile(fileName2, var1, var2);
      ::SysFreeString(fileName2);

      //下列代码展示了如何把数据从安全数组里面读取出来,并且保证内存不泄露
      pArray1 = var1.parray;
      pArray2 = var2.parray;

      //获取安全数组的上下边界以及长度
      long plLowBound, plUpperBound;
      SafeArrayGetLBound(pArray1, 1, &plLowBound);
      SafeArrayGetUBound(pArray1, 1, &plUpperBound);
      int wordCount = plUpperBound - plLowBound + 1;
      char **wordArray = new char*;
      int *frequencyArray = new int;
      VARIANT temp1, temp2;
      VariantInit(&temp1);
      VariantInit(&temp2);
      for (long i = plLowBound; i <= plUpperBound; i++)
      {
                ::SafeArrayGetElement(pArray1, &i, &temp1);
                ::SafeArrayGetElement(pArray2, &i, &temp2);
                wordArray = _com_util::ConvertBSTRToString(temp1.bstrVal);
                frequencyArray = temp2.intVal;
      }

      //把从安全数组读取出来的数据打印到屏幕上
      for (long i = plLowBound; i <= plUpperBound; i++)
      {
                printf("%s %d\n", wordArray, frequencyArray);
      }

      //调用searchWord搜索指定单词出现频率
      BSTR theWord = _com_util::ConvertStringToBSTR("the");
      long frequency = 0;
      wordCountServicePtr->searchWord(theWord, var1, var2, &frequency);
      ::SysFreeString(theWord);
      printf("所搜索的单词在文本出现频数为%ld次\n", frequency);

      for (long i = plLowBound; i <= plUpperBound; i++)
      {
                ::SafeArrayGetElement(pArray1, &i, &temp1);
                //释放掉安全数组里面的bstr内存
                ::SysFreeString(temp1.bstrVal);
                //释放掉字符串内存
                delete wordArray;
      }
      delete[] wordArray;
      delete[] frequencyArray;

      //安全数组使用完毕之后记得销毁
      SafeArrayDestroy(pArray1);
      SafeArrayDestroy(pArray2);
      //释放智能指针
      wordCountServicePtr.Release();
      //卸载com组件
      CoUninitialize();
      return 0;
}

页: [1]
查看完整版本: C++ COM组件字符串数组的传递