2004-09-09 Martin Baulig <martin@ximian.com>
[mono.git] / mono / tests / pinvoke2.cs
1 using System;
2 using System.Text;
3 using System.Runtime.InteropServices;
4
5 public class Tests {
6
7         public static int delegate_test (int a)
8         {
9                 if (a == 2)
10                         return 0;
11
12                 return 1;
13         }
14         
15         [StructLayout (LayoutKind.Sequential)]
16         public struct SimpleStruct {
17                 public bool a;
18                 public bool b;
19                 public bool c;
20                 public string d;
21         }
22
23         [StructLayout (LayoutKind.Sequential)]
24         public struct SimpleStruct2 {
25                 public bool a;
26                 public bool b;
27                 public bool c;
28                 public string d;
29                 public byte e;
30                 public double f;
31                 public byte g;
32                 public long h;
33         }
34
35         [StructLayout (LayoutKind.Sequential, Size=0)]
36         public struct EmptyStruct {
37         }
38
39         [StructLayout (LayoutKind.Sequential)]
40         public struct DelegateStruct {
41                 public int a;
42                 public SimpleDelegate del;
43                 [MarshalAs(UnmanagedType.FunctionPtr)] 
44                 public SimpleDelegate del2;
45         }
46
47         /* sparcv9 has complex conventions when passing structs with doubles in them 
48            by value, some simple tests for them */
49         [StructLayout (LayoutKind.Sequential)]
50         public struct Point {
51                 public double x;
52                 public double y;
53         }
54
55         [StructLayout (LayoutKind.Sequential)]
56         public struct MixedPoint {
57                 public int x;
58                 public double y;
59         }
60
61         [StructLayout (LayoutKind.Sequential)]
62         public class SimpleClass {
63                 public bool a;
64                 public bool b;
65                 public bool c;
66                 public string d;
67                 public byte e;
68                 public double f;
69                 public byte g;
70                 public long h;
71         }
72
73         [StructLayout (LayoutKind.Sequential)]
74         public class EmptyClass {
75         }
76
77         [StructLayout (LayoutKind.Sequential)]
78         public struct LongAlignStruct {
79                 public int a;
80                 public long b;
81                 public long c;
82         }
83
84         [StructLayout(LayoutKind.Sequential)]
85         public class VectorList
86         {
87                 public int a = 1;
88                 public int b = 2;
89         }
90
91         [StructLayout (LayoutKind.Sequential)]
92         class SimpleObj
93         {
94                 public string str;
95                 public int i;
96         }
97
98         [DllImport ("libnot-found", EntryPoint="not_found")]
99         public static extern int mono_library_not_found ();
100
101         [DllImport ("libtest", EntryPoint="not_found")]
102         public static extern int mono_entry_point_not_found ();
103
104         [DllImport ("libtest.dll", EntryPoint="mono_test_marshal_char")]
105         public static extern int mono_test_marshal_char_2 (char a1);
106
107         [DllImport ("libtest", EntryPoint="mono_test_marshal_char")]
108         public static extern int mono_test_marshal_char (char a1);
109
110         [DllImport ("libtest", EntryPoint="mono_test_marshal_char_array")]
111         public static extern int mono_test_marshal_char_array (char[] a1);
112
113         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_byref")]
114         public static extern int mono_test_marshal_bool_byref (int a, ref bool b, int c);
115
116         [DllImport ("libtest", EntryPoint="mono_test_marshal_array")]
117         public static extern int mono_test_marshal_array (int [] a1);
118
119         [DllImport ("libtest", EntryPoint="mono_test_marshal_empty_string_array")]
120         public static extern int mono_test_marshal_empty_string_array (string [] a1);
121
122         [DllImport ("libtest", EntryPoint="mono_test_marshal_string_array")]
123         public static extern int mono_test_marshal_string_array (string [] a1);
124
125         [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_string_array", CharSet=CharSet.Unicode)]
126         public static extern int mono_test_marshal_unicode_string_array (string [] a1, [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)]string [] a2);
127
128         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_array")]
129         public static extern int mono_test_marshal_stringbuilder_array (StringBuilder [] a1);   
130
131         [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_array")]
132         public static extern int mono_test_marshal_inout_array ([In, Out] int [] a1);
133
134         [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_nonblittable_array", CharSet = CharSet.Unicode)]
135         public static extern int mono_test_marshal_inout_nonblittable_array ([In, Out] char [] a1);
136         
137         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
138         public static extern int mono_test_marshal_struct (SimpleStruct ss);
139
140         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2")]
141         public static extern int mono_test_marshal_struct2 (SimpleStruct2 ss);
142
143         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2_2")]
144         public static extern int mono_test_marshal_struct2_2 (int i, int j, int k, SimpleStruct2 ss);
145
146         [DllImport ("libtest", EntryPoint="mono_test_marshal_point")]
147         public static extern int mono_test_marshal_point (Point p);
148
149         [DllImport ("libtest", EntryPoint="mono_test_marshal_mixed_point")]
150         public static extern int mono_test_marshal_mixed_point (MixedPoint p);
151
152         [DllImport ("libtest", EntryPoint="mono_test_empty_struct")]
153         public static extern int mono_test_empty_struct (int a, EmptyStruct es, int b);
154
155         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct_array")]
156         public static extern int mono_test_marshal_struct_array (SimpleStruct2[] ss);
157
158         [DllImport ("libtest", EntryPoint="mono_test_marshal_long_align_struct_array")]
159         public static extern int mono_test_marshal_long_align_struct_array (LongAlignStruct[] ss);
160
161         [DllImport ("libtest", EntryPoint="mono_test_marshal_class")]
162         public static extern SimpleClass mono_test_marshal_class (int i, int j, int k, SimpleClass ss, int l);
163
164         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_class")]
165         public static extern int mono_test_marshal_byref_class (ref SimpleClass ss);
166
167         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate")]
168         public static extern int mono_test_marshal_delegate (SimpleDelegate d);
169
170         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate_struct")]
171         public static extern int mono_test_marshal_delegate_struct (DelegateStruct d);
172
173         [DllImport ("libtest", EntryPoint="mono_test_return_vtype")]
174         public static extern SimpleStruct mono_test_return_vtype (IntPtr i);
175
176         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder")]
177         public static extern void mono_test_marshal_stringbuilder (StringBuilder sb, int len);
178
179         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_unicode", CharSet=CharSet.Unicode)]
180         public static extern void mono_test_marshal_stringbuilder_unicode (StringBuilder sb, int len);
181
182         [DllImport ("libtest", EntryPoint="mono_test_last_error", SetLastError=true)]
183         public static extern void mono_test_last_error (int err);
184
185         [DllImport ("libtest", EntryPoint="mono_test_asany")]
186         public static extern int mono_test_asany ([MarshalAs (UnmanagedType.AsAny)] object o, int what);
187
188         [DllImport ("libtest", EntryPoint="mono_test_asany", CharSet=CharSet.Unicode)]
189         public static extern int mono_test_asany_unicode ([MarshalAs (UnmanagedType.AsAny)] object o, int what);
190
191         [DllImport ("libtest")]
192         static extern int class_marshal_test0 (SimpleObj obj);
193
194         [DllImport ("libtest")]
195         static extern void class_marshal_test1 (out SimpleObj obj);
196         
197         [DllImport ("libtest")]
198         static extern int class_marshal_test2 (ref SimpleObj obj);
199
200         [DllImport ("libtest")]
201         static extern int class_marshal_test4 (SimpleObj obj);
202
203         public delegate int SimpleDelegate (int a);
204
205         public static int Main (string[] args) {
206                 return TestDriver.RunTests (typeof (Tests), args);
207         }
208
209         static int test_0_marshal_char () {
210                 return mono_test_marshal_char ('a');
211         }
212
213         static int test_0_marshal_char_array () {
214                 // char[] is implicitly marshalled as [Out]
215                 char[] buf = new char [32];
216                 mono_test_marshal_char_array (buf);
217                 string s = new string (buf);
218                 if (s.StartsWith ("abcdef"))
219                         return 0;
220                 else
221                         return 1;
222         }
223
224         static int test_1225_marshal_array () {
225                 int [] a1 = new int [50];
226                 for (int i = 0; i < 50; i++)
227                         a1 [i] = i;
228
229                 return mono_test_marshal_array (a1);
230         }
231
232         static int test_1225_marshal_inout_array () {
233                 int [] a1 = new int [50];
234                 for (int i = 0; i < 50; i++)
235                         a1 [i] = i;
236
237                 int res = mono_test_marshal_inout_array (a1);
238
239                 for (int i = 0; i < 50; i++)
240                         if (a1 [i] != 50 - i) {
241                                 Console.WriteLine ("X: " + i + " " + a1 [i]);
242                                 return 2;
243                         }
244
245                 return res;
246         }
247
248         static int test_0_marshal_inout_nonblittable_array () {
249                 char [] a1 = new char [10];
250                 for (int i = 0; i < 10; i++)
251                         a1 [i] = "Hello, World" [i];
252
253                 int res = mono_test_marshal_inout_nonblittable_array (a1);
254
255                 for (int i = 0; i < 10; i++)
256                         if (a1 [i] != 'F')
257                                 return 2;
258
259                 return res;
260         }
261
262         static int test_0_marshal_struct () {
263                 SimpleStruct ss = new  SimpleStruct ();
264                 ss.b = true;
265                 ss.d = "TEST";
266                 
267                 return mono_test_marshal_struct (ss);
268         }
269
270         static int test_0_marshal_struct2 () {
271                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
272                 ss2.b = true;
273                 ss2.d = "TEST";
274                 ss2.e = 99;
275                 ss2.f = 1.5;
276                 ss2.g = 42;
277                 ss2.h = 123L;
278
279                 return mono_test_marshal_struct2 (ss2);
280         }
281
282         static int test_0_marshal_struct3 () {
283                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
284                 ss2.b = true;
285                 ss2.d = "TEST";
286                 ss2.e = 99;
287                 ss2.f = 1.5;
288                 ss2.g = 42;
289                 ss2.h = 123L;
290
291                 return mono_test_marshal_struct2_2 (10, 11, 12, ss2);
292         }
293
294         static int test_0_marshal_empty_struct () {
295                 EmptyStruct es = new EmptyStruct ();
296
297                 if (mono_test_empty_struct (1, es, 2) != 0)
298                         return 1;
299                 
300                 return 0;
301         }
302
303         static int test_0_marshal_struct_array () {
304                 SimpleStruct2[] ss_arr = new SimpleStruct2 [2];
305
306                 SimpleStruct2 ss2 = new SimpleStruct2 ();
307                 ss2.b = true;
308                 ss2.d = "TEST";
309                 ss2.e = 99;
310                 ss2.f = 1.5;
311                 ss2.g = 42;
312                 ss2.h = 123L;
313
314                 ss_arr [0] = ss2;
315
316                 ss2.b = false;
317                 ss2.d = "TEST2";
318                 ss2.e = 100;
319                 ss2.f = 2.5;
320                 ss2.g = 43;
321                 ss2.h = 124L;
322
323                 ss_arr [1] = ss2;
324
325                 return mono_test_marshal_struct_array (ss_arr);
326         }
327
328         static int test_105_marshal_long_align_struct_array () {
329                 LongAlignStruct[] ss_arr = new LongAlignStruct [2];
330
331                 LongAlignStruct ss = new LongAlignStruct ();
332                 ss.a = 5;
333                 ss.b = 10;
334                 ss.c = 15;
335
336                 ss_arr [0] = ss;
337
338                 ss.a = 20;
339                 ss.b = 25;
340                 ss.c = 30;
341
342                 ss_arr [1] = ss;
343
344                 return mono_test_marshal_long_align_struct_array (ss_arr);
345         }
346
347         /* Test classes as arguments and return values */
348         static int test_0_marshal_class () {
349                 SimpleClass ss = new  SimpleClass ();
350                 ss.b = true;
351                 ss.d = "TEST";
352                 ss.e = 99;
353                 ss.f = 1.5;
354                 ss.g = 42;
355                 ss.h = 123L;
356
357                 SimpleClass res = mono_test_marshal_class (10, 11, 12, ss, 14);
358                 if (res == null)
359                         return 1;
360                 if  (! (res.a == ss.a && res.b == ss.b && res.c == ss.c && 
361                                 res.d == ss.d && res.e == ss.e && res.f == ss.f &&
362                                 res.g == ss.g && res.h == ss.h))
363                         return 2;
364
365                 /* Test null arguments and results */
366                 res = mono_test_marshal_class (10, 11, 12, null, 14);
367                 if (res != null)
368                         return 3;
369
370                 return 0;
371         }
372
373         static int test_0_marshal_byref_class () {
374                 SimpleClass ss = new  SimpleClass ();
375                 ss.b = true;
376                 ss.d = "TEST";
377                 ss.e = 99;
378                 ss.f = 1.5;
379                 ss.g = 42;
380                 ss.h = 123L;
381
382                 int res = mono_test_marshal_byref_class (ref ss);
383                 if (ss.d != "TEST-RES")
384                         return 1;
385
386                 return 0;
387         }
388
389         static int test_0_marshal_delegate () {
390                 SimpleDelegate d = new SimpleDelegate (delegate_test);
391
392                 return mono_test_marshal_delegate (d);
393         }
394
395         static int test_0_marshal_delegate_struct () {
396                 DelegateStruct s = new DelegateStruct ();
397
398                 s.a = 2;
399                 s.del = new SimpleDelegate (delegate_test);
400                 s.del2 = new SimpleDelegate (delegate_test);
401
402                 return mono_test_marshal_delegate_struct (s);
403         }
404
405         static int test_0_marshal_point () {
406                 Point pt = new Point();
407                 pt.x = 1.25;
408                 pt.y = 3.5;
409                 
410                 return mono_test_marshal_point(pt);
411         }
412
413         static int test_0_marshal_mixed_point () {
414                 MixedPoint mpt = new MixedPoint();
415                 mpt.x = 5;
416                 mpt.y = 6.75;
417                 
418                 return mono_test_marshal_mixed_point(mpt);
419         }
420
421         static int test_0_marshal_bool_byref () {
422                 bool b = true;
423                 if (mono_test_marshal_bool_byref (99, ref b, 100) != 1)
424                         return 1;
425                 b = false;
426                 if (mono_test_marshal_bool_byref (99, ref b, 100) != 0)
427                         return 12;
428                 if (b != true)
429                         return 13;
430
431                 return 0;
432         }
433
434         static int test_0_return_vtype () {
435                 SimpleStruct ss = mono_test_return_vtype (new IntPtr (5));
436
437                 if (!ss.a && ss.b && !ss.c && ss.d == "TEST")
438                         return 0;
439                 
440                 return 1;
441         }
442
443         static int test_0_marshal_stringbuilder () {
444                 StringBuilder sb = new StringBuilder(255);
445                 sb.Append ("ABCD");
446                 mono_test_marshal_stringbuilder (sb, sb.Capacity);
447                 String res = sb.ToString();
448
449                 if (res != "This is my message.  Isn't it nice?")
450                         return 1;  
451                 
452                 return 0;
453         }
454
455         static int test_0_marshal_stringbuilder_unicode () {
456                 StringBuilder sb = new StringBuilder(255);
457                 mono_test_marshal_stringbuilder_unicode (sb, sb.Capacity);
458                 String res = sb.ToString();
459
460                 if (res != "This is my message.  Isn't it nice?")
461                         return 1;  
462                 
463                 return 0;
464         }
465
466         static int test_0_marshal_empty_string_array () {
467                 return mono_test_marshal_empty_string_array (null);
468         }
469
470         static int test_0_marshal_string_array () {
471                 return mono_test_marshal_string_array (new String [] { "ABC", "DEF" });
472         }
473
474         static int test_0_marshal_unicode_string_array () {
475                 return mono_test_marshal_unicode_string_array (new String [] { "ABC", "DEF" }, new String [] { "ABC", "DEF" });
476         }
477
478         static int test_0_marshal_stringbuilder_array () {
479                 StringBuilder sb1 = new StringBuilder ("ABC");
480                 StringBuilder sb2 = new StringBuilder ("DEF");
481
482                 int res = mono_test_marshal_stringbuilder_array (new StringBuilder [] { sb1, sb2 });
483                 if (res != 0)
484                         return res;
485                 if (sb1.ToString () != "DEF")
486                         return 5;
487                 if (sb2.ToString () != "ABC")
488                         return 6;
489                 return 0;
490         }
491
492         static int test_0_last_error () {
493                 mono_test_last_error (5);
494                 if (Marshal.GetLastWin32Error () == 5)
495                         return 0;
496                 else
497                         return 1;
498         }
499
500         static int test_0_library_not_found () {
501
502                 try {
503                         mono_entry_point_not_found ();
504                         return 1;
505                 }
506                 catch (EntryPointNotFoundException) {
507                 }
508
509                 return 0;
510         }
511
512         static int test_0_entry_point_not_found () {
513
514                 try {
515                         mono_library_not_found ();
516                         return 1;
517                 }
518                 catch (DllNotFoundException) {
519                 }
520
521                 return 0;
522         }
523
524         /* Check that the runtime trims .dll from the library name */
525         static int test_0_trim_dll_from_name () {
526
527                 mono_test_marshal_char_2 ('A');
528
529                 return 0;
530         }
531
532         class C {
533                 public int i;
534         }
535
536         static int test_0_asany () {
537                 if (mono_test_asany (5, 1) != 0)
538                         return 1;
539
540                 if (mono_test_asany ("ABC", 2) != 0)
541                         return 2;
542
543                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
544                 ss2.b = true;
545                 ss2.d = "TEST";
546                 ss2.e = 99;
547                 ss2.f = 1.5;
548                 ss2.g = 42;
549                 ss2.h = 123L;
550
551                 if (mono_test_asany (ss2, 3) != 0)
552                         return 3;
553
554                 if (mono_test_asany_unicode ("ABC", 4) != 0)
555                         return 4;
556
557                 try {
558                         C c = new C ();
559                         c.i = 5;
560                         mono_test_asany (c, 0);
561                         return 5;
562                 }
563                 catch (ArgumentException) {
564                 }
565
566                 try {
567                         mono_test_asany (new Object (), 0);
568                         return 6;
569                 }
570                 catch (ArgumentException) {
571                 }
572
573                 return 0;
574         }
575
576         /* Byref String Array */
577
578         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_string_array")]
579         public static extern int mono_test_marshal_byref_string_array (ref string[] data);
580
581         public static int test_0_byref_string_array () {
582
583                 string[] arr = null;
584
585                 if (mono_test_marshal_byref_string_array (ref arr) != 0)
586                         return 1;
587
588                 arr = new string[] { "Alpha", "Beta", "Gamma" };
589
590                 if (mono_test_marshal_byref_string_array (ref arr) != 1)
591                         return 2;
592
593                 /* FIXME: Test returned array and out case */
594
595                 return 0;
596         }
597
598         /*
599          * AMD64 small structs-by-value tests.
600          */
601
602         /* TEST 1: 16 byte long INTEGER struct */
603
604         [StructLayout(LayoutKind.Sequential)]
605         public struct Amd64Struct1 {
606                 public int i;
607                 public int j;
608                 public int k;
609                 public int l;
610         }
611         
612         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")]
613         public static extern Amd64Struct1 mono_test_marshal_amd64_pass_return_struct1 (Amd64Struct1 s);
614
615         public static int test_0_amd64_struct1 () {
616                 Amd64Struct1 s = new Amd64Struct1 ();
617                 s.i = 5;
618                 s.j = -5;
619                 s.k = 0xffffff;
620                 s.l = 0xfffffff;
621
622                 Amd64Struct1 s2 = mono_test_marshal_amd64_pass_return_struct1 (s);
623
624                 return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1;
625         }
626
627         /* TEST 2: 8 byte long INTEGER struct */
628
629         [StructLayout(LayoutKind.Sequential)]
630         public struct Amd64Struct2 {
631                 public int i;
632                 public int j;
633         }
634         
635         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct2")]
636         public static extern Amd64Struct2 mono_test_marshal_amd64_pass_return_struct2 (Amd64Struct2 s);
637
638         public static int test_0_amd64_struct2 () {
639                 Amd64Struct2 s = new Amd64Struct2 ();
640                 s.i = 5;
641                 s.j = -5;
642
643                 Amd64Struct2 s2 = mono_test_marshal_amd64_pass_return_struct2 (s);
644
645                 return ((s2.i == 6) && (s2.j == -4)) ? 0 : 1;
646         }
647
648         /* TEST 3: 4 byte long INTEGER struct */
649
650         [StructLayout(LayoutKind.Sequential)]
651         public struct Amd64Struct3 {
652                 public int i;
653         }
654         
655         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct3")]
656         public static extern Amd64Struct3 mono_test_marshal_amd64_pass_return_struct3 (Amd64Struct3 s);
657
658         public static int test_0_amd64_struct3 () {
659                 Amd64Struct3 s = new Amd64Struct3 ();
660                 s.i = -5;
661
662                 Amd64Struct3 s2 = mono_test_marshal_amd64_pass_return_struct3 (s);
663
664                 return (s2.i == -4) ? 0 : 1;
665         }
666
667         /* Test 4: 16 byte long FLOAT struct */
668
669         [StructLayout(LayoutKind.Sequential)]
670         public struct Amd64Struct4 {
671                 public double d1, d2;
672         }
673         
674         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct4")]
675         public static extern Amd64Struct4 mono_test_marshal_amd64_pass_return_struct4 (Amd64Struct4 s);
676
677         public static int test_0_amd64_struct4 () {
678                 Amd64Struct4 s = new Amd64Struct4 ();
679                 s.d1 = 5.0;
680                 s.d2 = -5.0;
681
682                 Amd64Struct4 s2 = mono_test_marshal_amd64_pass_return_struct4 (s);
683
684                 return (s2.d1 == 6.0 && s2.d2 == -4.0) ? 0 : 1;
685         }
686
687         /* Blittable class */
688         [DllImport("libtest")]
689         private static extern VectorList TestVectorList (VectorList vl);
690
691         public static int test_0_marshal_blittable_class () {
692                 VectorList v1 = new VectorList ();
693
694                 /* Since it is blittable, it looks like it is passed as in/out */
695                 VectorList v2 = TestVectorList (v1);
696
697                 if (v1.a != 2 || v1.b != 3)
698                         return 1;
699                 
700                 if (v2.a != 2 || v2.b != 3)
701                         return 2;
702                 
703                 return 0;
704         }
705
706         static int test_0_marshal_byval_class () {
707                 SimpleObj obj0 = new SimpleObj ();
708                 obj0.str = "T1";
709                 obj0.i = 4;
710                 
711                 if (class_marshal_test0 (obj0) != 0)
712                         return 1;
713
714                 return 0;
715         }
716
717         static int test_0_marshal_byval_class_null () {
718                 if (class_marshal_test4 (null) != 0)
719                         return 1;
720
721                 return 0;
722         }
723
724         static int test_0_marshal_out_class () {
725                 SimpleObj obj1;
726
727                 class_marshal_test1 (out obj1);
728
729                 if (obj1.str != "ABC")
730                         return 1;
731
732                 if (obj1.i != 5)
733                         return 2;
734
735                 return 0;
736         }
737 }
738