@@ -44,7 +44,7 @@ namespace safearray {
4444 bounds.cElements =length;
4545 bounds.lLbound =0 ;
4646 SAFEARRAY* psa = SafeArrayCreate (itemType,1 ,&bounds);
47-
47+
4848
4949 XDUCER::JavaType* pSrc = JARRAY::lock (env,static_cast <JARRAY::ARRAY>(javaArray));
5050 XDUCER::NativeType* pDst;
@@ -60,31 +60,220 @@ namespace safearray {
6060 }
6161
6262 static JavaType toJava ( JNIEnv* env, NativeType psa ) {
63- XDUCER::NativeType* pSrc;
63+ ToJavaMultiDimlArrayMarshaller<itemType, XDUCER> m (env, psa);
64+ return m.getJava ();
65+ }
6466
65- long lbound,ubound; HRESULT hr;
66- hr = SafeArrayGetLBound (psa,1 ,&lbound);
67- hr = SafeArrayGetUBound (psa,1 ,&ubound);
68- // sometimes SafeArrayGetUBound returns -1 with S_OK. I haven't figured out what that means
69- int size = max (0 ,ubound-lbound+1 ); // the range of index is [lbound,ubound]
67+ };
7068
71- JARRAY::ARRAY a = JARRAY::newArray (env,size);
72- XDUCER::JavaType* pDst = JARRAY::lock (env,a);
69+ // convert between SAFEARRAY and Java primitive array
70+ template < VARTYPE vt, class NT , class JT >
71+ class PrimitiveArrayXducer : public BasicArrayXducer < vt, xducer::IdentityXducer<NT,JT> > {
72+ };
73+
74+
75+
76+ // Class to marshal SAFEARRAY to Java multi dimensional array
77+ //
78+ // itemType : array item type
79+ // XDUCER : converter for each array item
80+ template < VARTYPE itemType, class XDUCER >
81+ class ToJavaMultiDimlArrayMarshaller {
82+ typedef array::Array<typename XDUCER::JavaType> JARRAY;
83+ typedef SAFEARRAY* NativeType;
84+ typedef jarray JavaType;
85+
86+
87+ private:
88+ JNIEnv* env;
89+ NativeType psa;
90+ JavaType javaArray;
91+ int dim;
92+ int * dimSizes;
93+ typename XDUCER::NativeType* pSrc;
94+
95+ public:
96+ ToJavaMultiDimlArrayMarshaller (JNIEnv* _env, NativeType _psa)
97+ : env(_env)
98+ , psa(_psa)
99+ , dim(0 )
100+ , dimSizes(NULL )
101+ , pSrc(NULL )
102+ {
103+ dim = SafeArrayGetDim (psa);
104+ dimSizes = new int [dim];
105+ fillDimSizes (psa, dim, dimSizes);
73106 SafeArrayAccessData ( psa, reinterpret_cast <void **>(&pSrc) );
107+ }
108+
109+ ~ToJavaMultiDimlArrayMarshaller () {
110+ SafeArrayUnaccessData ( psa );
111+ delete[] dimSizes;
112+ }
74113
75- for ( int i=0 ; i<size; i++ ) {
76- pDst[i] = XDUCER::toJava (env,pSrc[i]);
114+ JavaType getJava () {
115+ return toJavaRec (pSrc, dim - 1 );
116+ }
117+
118+ private:
119+
120+ JavaType toJavaRec (typename XDUCER::NativeType* &pSrc, int curDim) {
121+ if (curDim == 0 ) {
122+ JARRAY::ARRAY a = JARRAY::newArray (env, dimSizes[curDim]);
123+ XDUCER::JavaType* const pDst = JARRAY::lock (env, a);
124+
125+ for ( int i=0 ; i < dimSizes[curDim]; i++ ) {
126+ pDst[i] = XDUCER::toJava (env, *(pSrc++));
127+ }
128+ JARRAY::unlock (env, a, pDst);
129+ return a;
77130 }
131+ else {
132+ jobjectArray a = array::Array<jobject>::newArray (env, dimSizes[curDim]);
133+ jobject* const pDst = array::Array<jobject>::lock (env, a);
78134
79- SafeArrayUnaccessData ( psa );
80- JARRAY::unlock (env,a,pDst);
135+ for ( int i = 0 ; i < dimSizes[curDim]; i++ ) {
136+ pDst[i] = toJavaRec (pSrc, curDim - 1 );
137+ }
138+ array::Array<jobject>::unlock (env, a, pDst);
139+ return a;
140+ }
81141
82- return a;
83142 }
143+
144+ static void fillDimSizes (NativeType psa, int dim, int *dimSizes) {
145+ for (int i = 1 ; i <= dim; ++i) {
146+ long lbound,ubound;
147+ SafeArrayGetLBound (psa,i,&lbound);
148+ SafeArrayGetUBound (psa,i,&ubound);
149+ // sometimes SafeArrayGetUBound returns -1 with S_OK. I haven't figured out what that means
150+ dimSizes[i-1 ] = max (0 ,ubound-lbound+1 ); // the range of index is [lbound,ubound]
151+ }
152+ }
153+
154+
84155 };
85156
86- // convert between SAFEARRAY and Java primitive array
87- template < VARTYPE vt, class NT , class JT >
88- class PrimitiveArrayXducer : public BasicArrayXducer < vt, xducer::IdentityXducer<NT,JT> > {
157+
158+
159+
160+ // Transducer that turns a Java multi dimensinal array into SAFEARRAY
161+ //
162+ // itemType : array item type
163+ // XDUCER : converter for each array item
164+ template < class XDUCER >
165+ class MultiDimArrayXducer {
166+ public:
167+ typedef SAFEARRAY* NativeType;
168+ typedef jarray JavaType;
169+
170+ static NativeType toNative ( JNIEnv* env, JavaType javaArray ) {
171+ ToNativeMultiDimlArrayMarshaller<VT_VARIANT, XDUCER> m (env, javaArray);
172+ return m.getNative ();
173+ }
174+
175+ };
176+
177+
178+
179+ // Class to marshall Java multi dimensional arrays to SAFEARRAY
180+ //
181+ // itemType : array item type
182+ // XDUCER : converter for each array item
183+ template < VARTYPE itemType, class XDUCER >
184+ class ToNativeMultiDimlArrayMarshaller {
185+ typedef array::Array<typename XDUCER::JavaType> JARRAY;
186+ typedef SAFEARRAY* NativeType;
187+ typedef jarray JavaType;
188+
189+
190+ private:
191+ JNIEnv* env;
192+ JavaType javaArray;
193+ int dim;
194+ SAFEARRAYBOUND* bounds;
195+ SAFEARRAY* psa;
196+ typename XDUCER::NativeType* pDst;
197+
198+ public:
199+ ToNativeMultiDimlArrayMarshaller (JNIEnv* _env, JavaType _javaArray)
200+ : env(_env)
201+ , javaArray(_javaArray)
202+ , dim(0 )
203+ , bounds(NULL )
204+ , psa(NULL )
205+ , pDst(NULL )
206+ {
207+ dim = getArrayDimension (env, javaArray);
208+ bounds = new SAFEARRAYBOUND[dim];
209+ fillBounds (env, javaArray, dim, bounds);
210+ psa = SafeArrayCreate (itemType, dim, bounds);
211+ SafeArrayAccessData ( psa, reinterpret_cast <void **>(&pDst) );
212+ }
213+
214+ ~ToNativeMultiDimlArrayMarshaller () {
215+ SafeArrayUnaccessData ( psa );
216+ delete[] bounds;
217+ }
218+
219+ SAFEARRAY* getNative () {
220+ toNativeRec (javaArray, dim - 1 );
221+ return psa;
222+ }
223+
224+ private:
225+ void toNativeRec (JavaType _array, int curDim) {
226+
227+ if (curDim == 0 ) {
228+ XDUCER::JavaType* pSrc = JARRAY::lock (env,static_cast <JARRAY::ARRAY>(_array));
229+
230+ for (size_t i = 0 ; i < bounds[curDim].cElements ; i++)
231+ *(pDst++) = XDUCER::toNative (env, pSrc[i]);
232+
233+ JARRAY::unlock (env,static_cast <JARRAY::ARRAY>(_array), pSrc);
234+
235+ }
236+ else {
237+ JavaType* pSrc = array::Array<JavaType>::lock (env, static_cast <JARRAY::ARRAY>(_array));
238+
239+ for (size_t i = 0 ; i < bounds[curDim].cElements ; i++)
240+ toNativeRec (pSrc[i], curDim - 1 );
241+
242+ array::Array<JavaType>::unlock (env,static_cast <JARRAY::ARRAY>(_array), pSrc);
243+ }
244+ }
245+
246+ // gets dimensions of java multi index array
247+ static int getArrayDimension (JNIEnv* env, jobject a ) {
248+ int dim = 0 ;
249+ while (env->IsInstanceOf (a, objectArray)) {
250+ dim++;
251+
252+ if (env->GetArrayLength (static_cast <jobjectArray>(a)) > 0 )
253+ a = env->GetObjectArrayElement (static_cast <jobjectArray>(a), 0 );
254+ else
255+ return dim;
256+ };
257+
258+ return dim;
259+ }
260+
261+ // fills SAFEARRAYBOUND structure base on java array
262+ static void fillBounds (JNIEnv* env, jobject a, int n, SAFEARRAYBOUND* bounds) {
263+ int i = n - 1 ;
264+ while (true ) {
265+ bounds[i].lLbound = 0 ;
266+ bounds[i].cElements = env->GetArrayLength (static_cast <jobjectArray>(a));
267+
268+ if (i <= 0 )
269+ break ;
270+
271+ a = env->GetObjectArrayElement (static_cast <jobjectArray>(a), 0 );
272+ i--;
273+ }
274+ }
275+
89276 };
277+
278+
90279}
0 commit comments