C++ OPC write string array using Softing OPC-Classic-SDK

70 Views Asked by At

I know this is the way to write floating point array

     Variant Data;
     DateTime CurrentTime;
     CurrentTime.now();               

     double* ArrayVar;
     Data.SafeArrayAccessData(Data.parray, reinterpret_cast<void**>(&ArrayVar));
     std::memcpy(ArrayVar, Values.data(), Values.size() * sizeof(double));
     SafeArrayUnaccessData(Data.parray);

     ItemValues.emplace_back(new ValueQT((Data), EnumQuality_QUALITY_NOT_SET, CurrentTime));
     ItemNames.emplace_back(ItemName);
     ItemPaths.emplace_back(L"");

     // auto Session = new DaSession(URL);

     Session->write(Items, Paths, const_cast<std::vector<ValueQT*>&>(Values), WriteResults, &ExecutionOptions_);


But how do I prepare a string array for writing? The following code will just crash.

     wchar_t** Temp = new wchar_t*[Size];
     for (int j = 0; j < Size; j++)
     {
          Temp[j] = new wchar_t[Values[j].size() + 1 ];
          std::wcscpy(Temp[j], Values[j].c_str());
     }
     wchar_t** ArrayVar;
     Data.SafeArrayAccessData(Data.parray, reinterpret_cast<void**>(&ArrayVar));

     std::memcpy(ArrayVar, Temp, Size * sizeof(wchar_t*));

     for (size_t j = 0; j < Size; j++)
     {
      std::wcscpy((ArrayVar[j]), (Temp[j]));
     }

     Data.SafeArrayUnaccessData(Data.parray); 

I need to use the OPC toolkit from https://github.com/SoftingIndustrial/OPC-Classic-SDK

The program also crashes if i don't use the for loop, with the same error message. Also the values are not set for ValueQT (with the string array).

1

There are 1 best solutions below

1
kpm On

If someone ever needs this here is a working solution:

//Values is std::vector<std::wstring>
Variant Data;
Data.vt = VT_BSTR | VT_ARRAY;
Data.parray = SafeArrayCreateVector(VT_BSTR, 0, Size);

wchar_t** ArrayVar;
ata.SafeArrayAccessData(Data.parray, reinterpret_cast<void**>(&ArrayVar));

    for(Py_ssize_t j = 0;  j < Size; j++)
    {
      BSTR temp = SysAllocString(Values[j].c_str());
      SafeArrayPutElement(Data.parray, reinterpret_cast<LONG*>( & j), temp);
      SysFreeString(temp);
    }
Data.SafeArrayUnaccessData(Data.parray);