ISIS Logo
lvDCOM
An EPICS support module to export LabVIEW values as process variables
variant_utils.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2013 Science and Technology Facilities Council (STFC), GB.
3 * All rights reverved.
4 * This file is distributed subject to a Software License Agreement found
5 * in the file LICENSE.txt that is included with this distribution.
6 \*************************************************************************/
7 
10 
11 //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
12 
13 #include <atlbase.h>
14 #include <atlcom.h>
15 #include <atlconv.h>
16 
17 #include <comdef.h>
18 
19 #include <ctime>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cctype>
23 #include <string>
24 #include <list>
25 #include <vector>
26 #include <map>
27 #include <sstream>
28 
29 #include "variant_utils.h"
30 
31 
32 std::string COMexception::com_message(const std::string& message, HRESULT hr)
33 {
34  _com_error ce(hr);
35  std::ostringstream oss;
36  oss << message << ": " << ce.ErrorMessage();
37  return oss.str();
38 }
39 
40 
41 std::string Win32StructuredException::win32_message(unsigned int code, EXCEPTION_POINTERS * pExp)
42 {
43  char buffer[256];
44  _snprintf(buffer, sizeof(buffer), "Win32StructuredException code 0x%x pExpCode 0x%x pExpAddress %p", code, pExp->ExceptionRecord->ExceptionCode, pExp->ExceptionRecord->ExceptionAddress);
45  buffer[sizeof(buffer)-1] = '\0';
46  return std::string(buffer);
47 }
48 
49 // 0 on success, -1 on error
50 
51 int allocateArrayVariant(VARIANT* v, VARTYPE v_type, int* dims_array, int ndims)
52 {
53  int i;
54  V_VT(v) = VT_ARRAY | v_type;
55  SAFEARRAYBOUND* sab = new SAFEARRAYBOUND[ndims];
56  if (sab == NULL)
57  {
58  return -1;
59  }
60  // safe arrays are index other way round to C
61  for(i=0; i<ndims; i++)
62  {
63  sab[i].lLbound = 1;
64  sab[i].cElements = dims_array[ndims-i-1];
65  }
66  V_UNION(v,parray) = SafeArrayCreate(v_type, ndims, sab);
67  delete []sab;
68  if (V_UNION(v,parray) == NULL)
69  {
70  return -1;
71  }
72  return 0;
73 }
74 
75 
76 static int accessArrayVariant(VARIANT* v, void** values, VARTYPE vt)
77 {
78  VARTYPE vtt;
79  HRESULT hr;
80  *values = NULL;
81  hr = SafeArrayGetVartype(V_UNION(v,parray), &vtt);
82  if (!(vtt & vt))
83  {
84  return -1;
85  }
86  hr = SafeArrayAccessData(V_UNION(v,parray), values);
87  if ( FAILED(hr) || (*values == NULL) )
88  {
89  *values = NULL;
90  return -1;
91  }
92  return 0;
93 }
94 
95 int accessArrayVariant(VARIANT* v, float** values)
96 {
97  return accessArrayVariant(v, (void**)values, VT_R4);
98 }
99 
100 int accessArrayVariant(VARIANT* v, double** values)
101 {
102  return accessArrayVariant(v, (void**)values, VT_R8);
103 }
104 
105 int accessArrayVariant(VARIANT* v, long** values)
106 {
107  return accessArrayVariant(v, (void**)values, VT_I4);
108 }
109 
110 int accessArrayVariant(VARIANT* v, BSTR** values)
111 {
112  return accessArrayVariant(v, (void**)values, VT_BSTR);
113 }
114 
115 int accessArrayVariant(VARIANT* v, VARIANT** values)
116 {
117  return accessArrayVariant(v, (void**)values, VT_VARIANT);
118 }
119 
120 int unaccessArrayVariant(VARIANT* v)
121 {
122  HRESULT hr = SafeArrayUnaccessData(V_UNION(v,parray));
123  if (FAILED(hr))
124  {
125  return -1;
126  }
127  return 0;
128 }
129 
130 
131 int arrayVariantLength(VARIANT* v)
132 {
133  if (!(V_VT(v) & VT_ARRAY))
134  {
135  return 0;
136  }
137  SAFEARRAY* psa = V_UNION(v,parray);
138  if (psa == NULL)
139  {
140  return 0;
141  }
142  int ndims = SafeArrayGetDim(psa);
143  if (ndims <= 0)
144  {
145  return 0;
146  }
147  long lbounds, ubounds;
148  int len = 1;
149  int i;
150  for(i=0; i<ndims; i++)
151  {
152  lbounds = ubounds = 0;
153  SafeArrayGetLBound(psa, i+1, &lbounds);
154  SafeArrayGetUBound(psa, i+1, &ubounds);
155  len *= (ubounds - lbounds + 1);
156  }
157  return len;
158 }
159 
160 int arrayVariantDimensions(VARIANT* v, int dims_array[], int& ndims)
161 {
162  ndims = 0;
163  dims_array[0] = 0;
164  if (!(V_VT(v) & VT_ARRAY))
165  {
166  return -1;
167  }
168  SAFEARRAY* psa = V_UNION(v,parray);
169  if (psa == NULL)
170  {
171  return -1;
172  }
173  ndims = SafeArrayGetDim(psa);
174  long lbounds, ubounds;
175  for(int i=0; i<ndims; i++)
176  {
177  lbounds = ubounds = 0;
178  SafeArrayGetLBound(psa, i+1, &lbounds);
179  SafeArrayGetUBound(psa, i+1, &ubounds);
180  dims_array[i] = ubounds - lbounds + 1;
181  }
182  return 0;
183 }
184 
185 template <typename T>
186 int makeVariantFromArray(VARIANT* v, const std::vector<T>& the_array)
187 {
188  return makeVariantFromArray(v, &(the_array[0]), static_cast<int>(the_array.size()));
189 }
190 
191 template <>
192 int makeVariantFromArray(VARIANT* v, const std::vector<std::string>& the_array)
193 {
194  int n = static_cast<int>(the_array.size());
195  allocateArrayVariant(v, VT_BSTR, &n, 1);
196  BSTR* v_array = NULL;
197  accessArrayVariant(v, &v_array);
198  for(int i=0; i<n; ++i)
199  {
200  CComBSTR bstr_wrapper(the_array[i].c_str());
201  v_array[i] = bstr_wrapper.Detach();
202  }
204  return 0;
205 }
206 
207 
208 template <const VARTYPE vt>
209 struct CPPType
210 {
211  typedef int type;
212 };
213 
214 template <>
215 struct CPPType<VT_I4>
216 {
217  typedef int type;
218 };
219 
220 template <>
221 struct CPPType<VT_R4>
222 {
223  typedef float type;
224 };
225 
226 template <typename T>
227 int makeVariantFromArray(VARIANT* v, const T* the_array, int n)
228 {
229  VARTYPE vt_type = CVarTypeInfo<T>::VT;
230  allocateArrayVariant(v, vt_type, &n, 1);
231  T* v_array = NULL;
232  accessArrayVariant(v, &v_array);
233  for(int i=0; i<n; ++i)
234  {
235  v_array[i] = the_array[i];
236  }
238  return 0;
239 }
240 
241 template <>
242 int makeVariantFromArray(VARIANT* v, const char* the_array, int n)
243 {
244  return -1;
245 }
246 
247 template int makeVariantFromArray(VARIANT* v, const std::vector<float>& the_array);
248 
int arrayVariantDimensions(VARIANT *v, int dims_array[], int &ndims)
int unaccessArrayVariant(VARIANT *v)
Header file for various COM utilities.
int allocateArrayVariant(VARIANT *v, VARTYPE v_type, int *dims_array, int ndims)
static int accessArrayVariant(VARIANT *v, void **values, VARTYPE vt)
int makeVariantFromArray(VARIANT *v, const std::vector< T > &the_array)
static std::string win32_message(unsigned int code, EXCEPTION_POINTERS *pExp)
int arrayVariantLength(VARIANT *v)
static std::string com_message(const std::string &message, HRESULT hr)
Copyright © 2013 Science and Technology Facilities Council | Generated by   doxygen 1.8.5