forked from rdotnet/rClr
-
Notifications
You must be signed in to change notification settings - Fork 3
/
rClr-exported.R
831 lines (776 loc) · 28.9 KB
/
rClr-exported.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
#' Shuts down the current runtime.
#'
#' Shuts down the current runtime.
#'
#' @return nothing is returned by this function
#' @export
clrShutdown <- function() { # TODO: is this even possible given runtime's constraints?
result <- .C("rclr_shutdown_clr", PACKAGE=nativePkgName)
}
#' Turn on/off R.NET
#'
#' Turn on or off the usage of the R.NET assemblies to convert CLR objects to R data structures. As of version 0.7.0, R.NET is the preferred way to convert data and is enabled by default.
#'
#' @param setit if true enable, otherwise disable
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' ## R.NET is currently used to convert complicated CLR types to sensible R equivalents
#' setRDotNet()
#' cTypename <- "Rclr.TestCases"
#' clrCallStatic(cTypename, "CreateStringDictionary")
#' setRDotNet(FALSE)
#' clrCallStatic(cTypename, "CreateStringDictionary")
#' }
setRDotNet <- function(setit=TRUE) {
invisible(clrCallStatic('Rclr.RDotNetDataConverter', 'SetRDotNet', setit))
}
#' Turn on/off the conversion of advanced data types with R.NET
#'
#' Turn on/off the conversion of advanced data types with R.NET. This will turn off the conversion of classes such as dictionaries into R lists,
#' as these are not bidirectional and you may want to see and manipulate external pointers to dictionaries in some circumstances.
#'
#' @param enable if true enable, otherwise disable
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' cTypename <- "Rclr.TestCases"
#' clrCallStatic(cTypename, "CreateStringDictionary")
#' setConvertAdvancedTypes(FALSE)
#' clrCallStatic(cTypename, "CreateStringDictionary")
#' }
setConvertAdvancedTypes <- function(enable=TRUE) {
invisible(clrCallStatic('Rclr.RDotNetDataConverter', 'SetConvertAdvancedTypes', enable))
}
#' Loads a Common Language assembly.
#'
#' Loads an assembly. Note that this is loaded in the single application domain that is created by rClr, not a separate application domain.
#'
#' @param name a character vector of length one. It can be the full file name of the assembly to load, or a fully qualified assembly name, or as a last resort a partial name.
#' @seealso \code{\link{.C}} which this function wraps
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' clrGetLoadedAssemblies()
#' f <- file.path('SomeDirectory', 'YourDotNetBinaryFile.dll')
#' f <- path.expand(f)
#' stopifnot( file.exists(f) )
#' clrLoadAssembly(f)
#' # Load an assembly from the global assembly cache (GAC)
#' clrLoadAssembly("System.Windows.Presentation,
#' Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
#' # The use of partial assembly names is discouraged; nevertheless it is supported
#' clrLoadAssembly("System.Web.Services")
#' clrGetLoadedAssemblies()
#' }
clrLoadAssembly <- function(name) {
# if( !file.exists(name) ) stop(paste("File not found: ", name))
result <- .C("rclr_load_assembly", name, PACKAGE=nativePkgName)
}
#' Gets the inner name used for the package
#'
#' Gets the inner name used for the package (rClrMono or rClrMs). This is not intented for use by most users.
#'
#' @return the short name of the library currently loaded, depending on the runtime used (Mono or Microsoft .NET)
#' @export
clrGetInnerPkgName <- function() { nativePkgName }
#' List the instance members of a CLR object
#'
#' List the instance members of a CLR object, i.e. its methods, fields and properties.
#'
#' @param clrobj CLR object
#' @return a list of methods, fields and properties of the CLR object
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrReflect(testObj)
#' }
clrReflect <- function( clrobj ) {
# .Call("r_reflect_on_object", clrobj@clrobj, silent=FALSE, PACKAGE="rClr")
list(Methods=clrGetMethods(clrobj), Fields=clrGetFields(clrobj), Properties=clrGetProperties(clrobj))
}
#' Calls the ToString method of an object
#'
#' Calls the ToString method of an object as represented in the CLR.
#' This function is here to help quickly test object equivalence from the R interpreter, for instance on the tricky topic of date-time conversions
#'
#' @param x any R object, which is converted to a CLR object on which to call ToString
#' @return the string representation of the object in the CLR
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' dt <- as.POSIXct('2001-01-01 02:03:04', tz='UTC')
#' clrToString(dt)
#' }
clrToString <- function(x) {
return(clrCallStatic(clrFacadeTypeName, 'ToString',x))
}
#' Prints the last CLR exception
#'
#' Prints the last CLR exception. This is roughly the equivalent of the traceback function of R.
#'
#' @export
#' @examples
#' \dontrun{
#' clrCallStatic("Rclr.TestCases", "ThrowException", 10L) # will be truncated by the Rf_error API
#' clrTraceback() # prints the full stack trace
#' }
clrTraceback <- function() {
cat(clrGet(clrFacadeTypeName, 'LastException'))
invisible(NULL)
}
#' List the names of loaded CLR assemblies
#'
#' List the names of loaded CLR assemblies
#'
#' @param fullname should the full name of the assemblies be returned
#' @param filenames if TRUE, return a data frame where the second column is the URI (usually file path) of the loaded assembly.
#' @return the names of loaded CLR assemblies
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' clrGetLoadedAssemblies()
#' }
clrGetLoadedAssemblies <- function(fullname=FALSE, filenames=FALSE) {
assNames <- clrCallStatic(reflectionHelperTypeName, 'GetLoadedAssemblyNames', fullname)
if(filenames) {
data.frame(AssemblyName=assNames, URI=clrCallStatic(reflectionHelperTypeName, 'GetLoadedAssemblyURI', assNames))
} else {
assNames
}
}
#' Get a list of CLR type names exported by an assembly
#'
#' Get a list of CLR type names exported by an assembly
#'
#' @param assemblyName the name of the assembly
#' @return the names of the types exported by the assembly
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' clrGetLoadedAssemblies()
#' clrGetTypesInAssembly('ClrFacade')
#' }
clrGetTypesInAssembly <- function(assemblyName) {
clrCallStatic(reflectionHelperTypeName, 'GetTypesInAssembly', assemblyName)
}
#' List the instance fields of a CLR object
#'
#' List the instance fields of a CLR object
#'
#' @param clrobj CLR object
#' @param contains a string that the field names returned must contain
#' @return a list of names of the fields of the CLR object
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrGetFields(testObj)
#' clrGetFields(testObj, 'ieldInt')
#' }
clrGetFields <- function( clrobj, contains = '') {
clrCallStatic(reflectionHelperTypeName, 'GetInstanceFields', clrobj, contains)
}
#' List the instance properties of a CLR object
#'
#' List the instance properties of a CLR object
#'
#' @param clrobj CLR object
#' @param contains a string that the property names returned must contain
#' @return a list of names of the properties of the CLR object
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrGetProperties(testObj)
#' clrGetProperties(testObj, 'One')
#' }
clrGetProperties <- function( clrobj, contains = '') {
clrCallStatic(reflectionHelperTypeName, 'GetInstanceProperties', clrobj, contains)
}
#' List the instance methods of a CLR object
#'
#' List the instance methods of a CLR object
#'
#' @param clrobj CLR object
#' @param contains a string that the methods names returned must contain
#' @return a list of names of the methods of the CLR object
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrGetMethods(testObj)
#' clrGetMethods(testObj, 'Get')
#' }
clrGetMethods <- function( clrobj, contains = '') {
clrCallStatic(reflectionHelperTypeName, 'GetInstanceMethods', clrobj, contains)
}
#' List the public constructors of a CLR Type
#'
#' List the public constructors of a CLR Type
#'
#' @param type CLR Type, or a (character) type name that can be successfully parsed
#' @return a list of constructor signatures
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' clrGetConstructors(testClassName)
#' }
clrGetConstructors <- function( type ) {
clrCallStatic(reflectionHelperTypeName, 'GetConstructors', type)
}
#' Gets the signature of a CLI object member
#'
#' Gets a string representation of the signature of a member (i.e. field, property, method).
#' Mostly used to interactively search for what arguments to pass to a method.
#'
#' @param clrobj CLR object
#' @param memberName The exact name of the member (i.e. field, property, method) to search for
#' @return a character vector with summary information on the method/member signatures
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrReflect(testObj)
#' clrGetMemberSignature(testObj, 'set_PropertyIntegerOne')
#' clrGetMemberSignature(testObj, 'FieldIntegerOne')
#' clrGetMemberSignature(testObj, 'PropertyIntegerTwo')
#' }
clrGetMemberSignature <- function( clrobj, memberName ) {
clrCallStatic(reflectionHelperTypeName, 'GetSignature', clrobj, memberName)
}
#' Create a new CLR object
#'
#' @param typename type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param ... additional method arguments passed to the object constructor via the call to .External
#' @return a CLR object
#' @export
#' @import methods
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' (testObj <- clrNew(testClassName))
#' # object with a constructor that has parameters
#' (testObj <- clrNew(testClassName, as.integer(123)))
#' clrLoadAssembly("System.Windows.Forms, Version=2.0.0.0,
#' Culture=neutral, PublicKeyToken=b77a5c561934e089")
#' f <- clrNew('System.Windows.Forms.Form')
#' clrSet(f, 'Text', "Hello from '.NET'")
#' clrCall(f, 'Show')
#' }
clrNew <- function(typename, ...)
{
o<-.External("r_create_clr_object", typename, ..., PACKAGE=nativePkgName)
if (is.null(o)) {
stop("Failed to create instance of type '",typename,"'")
}
mkClrObjRef(o, clrtype=typename)
}
#' System function to get a direct access to an object
#'
#' This function needs to be exported, but is highly unlikely to be of any use to an end user, even an advanced one.
#' This is indirectly needed to unlock the benefits of using R.NET convert data structures between R and .NET.
#' Using this function is a critical part of solving the rather complicated issue rClr #33.
#'
#' @return a CLR object
#' @export
getCurrentConvertedObject <- function()
{
o <-.External("r_get_object_direct", PACKAGE=nativePkgName)
mkClrObjRef(o)
}
#' Check whether an object is of a certain type
#'
#' Check whether an object is of a certain type. This function is meant to match the behavior of the 'is' keyword in C#.
#'
#' @param obj an object
#' @param type the object type to check for. It can be a character, of a object of CLR type System.RuntimeType
#' @return TRUE or FALSE
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' (testObj <- clrNew(testClassName))
#' clrIs(testObj, testClassName)
#' clrIs(testObj, 'System.Object')
#' clrIs(testObj, 'System.Double')
#' (testObj <- clrNew('Rclr.TestMethodBinding'))
#' # Test for interface definitions
#' clrIs(testObj, 'Rclr.ITestMethodBindings')
#' clrIs(testObj, clrGetType('Rclr.ITestMethodBindings'))
#' clrIs(testObj, clrGetType('Rclr.TestMethodBinding'))
#' clrIs(testObj, clrGetType('System.Reflection.Assembly'))
#' }
clrIs <- function(obj, type) {
if(is.character(type)) {
tmpType <- clrGetType(type)
if(is.null(tmpType)) {stop(paste('Unrecognized type name', type))} else {type <- tmpType}
}
if(!is(type, 'cobjRef')) {
stop(paste('argument "type" must be a CLR type name or a Type'))
} else {
typetypename <- clrGet(clrCall(type, 'GetType'), 'Name')
if(!(typetypename %in% c('RuntimeType', 'MonoType'))) {
stop(paste('argument "type" must be a CLR Type. Got a', typetypename))
}
}
objType <- clrGetType(obj)
return(clrCall(type, 'IsAssignableFrom', objType))
}
#' Call a method on an object
#'
#' @param obj an object
#' @param methodName the name of a method of the object
#' @param ... additional method arguments passed to .External
#' @return an object resulting from the call. May be a CLR object, or a native R object for common types. Can be NULL.
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' (testObj <- clrNew(testClassName))
#' clrCall(testObj, 'GetFieldIntegerOne')
#' ## derived from unit test for matching the right method (function) to call.
#' f <- function(...){ paste( 'This called a method with arguments:',
#' paste(clrCallStatic('Rclr.TestMethodBinding', 'SomeStaticMethod', ...), collapse=', ')) }
#' f(1:3)
#' f(3)
#' f('a')
#' f('a', 3)
#' f(3, 'a')
#' f(list('a', 3))
#' }
clrCall <- function(obj,methodName,...)
{
interface="r_call_method"
result <- NULL
result <-.External(interface, obj@clrobj, methodName, ..., PACKAGE=nativePkgName)
return(mkClrObjRef(result))
}
#' Gets the value of a field or property of an object or class
#'
#' @param objOrType a CLR object, or type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param name the name of a field/property of the object
#' @return an object resulting from the call. May be a CLR object, or a native R object for common types. Can be NULL.
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrReflect(testObj)
#' clrGet(testObj, 'FieldIntegerOne')
#' clrGet(testClassName, 'StaticPropertyIntegerOne')
#' }
clrGet <- function(objOrType,name)
{
return(clrCallStatic(clrFacadeTypeName, 'GetFieldOrProperty',objOrType, name))
}
#' Sets the value of a field or property of an object or class
#'
#' Sets the value of a field or property of an object or class
#'
#' @param objOrType a CLR object, or type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param name the name of a field/property of the object
#' @param value the value to set the field with
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrReflect(testObj)
#' clrSet(testObj, 'FieldIntegerOne', 42)
#' clrSet(testClassName, 'StaticPropertyIntegerOne', 42)
#'
#' # Using 'good old' Windows forms to say hello:
#' clrLoadAssembly("System.Windows.Forms, Version=2.0.0.0,
#' Culture=neutral, PublicKeyToken=b77a5c561934e089")
#' f <- clrNew('System.Windows.Forms.Form')
#' clrSet(f, 'Text', "Hello from '.NET'")
#' clrCall(f, 'Show')
#' }
clrSet <- function(objOrType, name, value)
{
invisible(clrCallStatic(clrFacadeTypeName, 'SetFieldOrProperty',objOrType, name, value))
}
#' Gets the names of a CLR Enum value type
#'
#' @param enumType a CLR object, System.Type or type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @return a character vector of the names for the enum
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' clrGetEnumNames('Rclr.TestEnum')
#' }
clrGetEnumNames <- function(enumType)
{
return(clrCallStatic(reflectionHelperTypeName, 'GetEnumNames',enumType))
}
#' Sets the value of an enum field or property of an object or class
#'
#' Sets the value of an enum field or property of an object or class
#'
#' @param objOrType a CLR object, or type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param name the name of a field/property of the object
#' @param enumtype type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param enumval the value to set the field with
#' @export
clrSetEnumProperty <- function(objOrType, name, enumtype, enumval)
{
stop('Not yet implemented')
return(clrCallStatic(reflectionHelperTypeName, 'SetEnumValue',objOrType, name, enumtype, enumval))
}
#' Gets the external pointer CLR object.
#'
#' Gets the external pointer CLR object. End user are unlikely to need this.
#'
#' @param clrObject a S4 object of class clrobj
#' @return the external pointer to the CLR object
#' @export
clrGetExtPtr <- function(clrObject) {
clrObject@clrobj
}
#' Gets the type name of an object
#'
#' Gets the type name of an object, given the SEXP external pointer to this CLR object.
#'
#' @param extPtr external pointer to a CLR object (not a cobjRef S4 object)
#' @return a character string, the type name
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrTypeNameExtPtr(clrGetExtPtr(testObj))
#' }
clrTypeNameExtPtr <- function(extPtr) {
checkIsExtPtr(extPtr)
.External("r_get_typename_externalptr", extPtr, PACKAGE=nativePkgName)
}
#' Gets the type name of an object
#'
#' Gets the CLR type name of an object, given an S4 clrobj object
#'
#' @param clrobj CLR object
#' @return type name
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrTypename(testObj)
#' }
clrTypename <- function(clrobj) {
name <- .Call("r_get_type_name", clrobj, PACKAGE=nativePkgName)
name
}
#' Gets the name of the native library currently loaded.
#'
#' Gets the name of the native library currently loaded. Used only for unit tests.
#'
#' @return the name of the native library currently loaded: rClrMs or rClrMono
#' @export
clrGetNativeLibName <- function() {
nativePkgName
}
#' Call a static method on a CLR type
#'
#' @param typename type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param methodName the name of a static method of the type
#' @param ... additional method arguments passed to .External
#' @return an object resulting from the call. May be a CLR object, or a native R object for common types. Can be NULL.
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' cTypename <- "Rclr.TestCases"
#' clrCallStatic(cTypename, "IsTrue", TRUE)
#' }
clrCallStatic <- function(typename, methodName,...)
{
extPtr <-.External("r_call_static_method", typename, methodName,..., PACKAGE=nativePkgName)
return(mkClrObjRef(extPtr))
}
#' Peek into the types of CLR objects arguments are converted to by rClr
#'
#' Advanced use only, to diagnose unexpected conditions in CLR method calls. Most users would not ever need it.
#'
#' @param ... method arguments passed to .External
#' @return a character message with type information about each argument.
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' peekClrArgs("a", numeric(0))
#' }
peekClrArgs <- function(...)
{
extPtr <-.External("r_diagnose_parameters", ..., PACKAGE=nativePkgName)
return(mkClrObjRef(extPtr))
}
#' Gets the static members for a type
#'
#' Gets the static members for a type
#'
#' @param objOrType a CLR object, or type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @export
#' @examples
#' \dontrun{
#' library(rClr)
#' cTypename <- "Rclr.TestCases"
#' clrGetStaticMembers(cTypename)
#' testClassName <- "Rclr.TestObject";
#' testObj <- clrNew(testClassName)
#' clrGetStaticMembers(testObj)
#' }
clrGetStaticMembers <- function(objOrType)
{
list(Methods=clrGetStaticMethods(objOrType), Fields=clrGetStaticFields(objOrType), Properties=clrGetStaticProperties(objOrType))
}
#' Gets the static fields for a type
#'
#' Gets the static fields for a type
#'
#' @param objOrType a CLR object, or type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param contains a string that the property names returned must contain
#' @export
clrGetStaticFields <- function( objOrType, contains = '') {
clrCallStatic(reflectionHelperTypeName, 'GetStaticFields', objOrType, contains)
}
#' Gets the static members for a type
#'
#' Gets the static members for a type
#'
#' @inheritParams clrGetStaticFields
#' @export
clrGetStaticProperties <- function( objOrType, contains = '') {
clrCallStatic(reflectionHelperTypeName, 'GetStaticProperties', objOrType, contains)
}
#' Gets the static members for a type
#'
#' @inheritParams clrGetStaticFields
#' @export
clrGetStaticMethods <- function( objOrType, contains = '') {
clrCallStatic(reflectionHelperTypeName, 'GetStaticMethods', objOrType, contains)
}
#' Gets the signature of a static member of a type
#'
#' @param typename type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param memberName The exact name of the member (i.e. field, property, method) to search for
#' @export
clrGetStaticMemberSignature <- function( typename, memberName ) {
clrCallStatic(reflectionHelperTypeName, 'GetSignature', typename, memberName)
}
#' Architecture dependent path to the rClr native library
#'
#' Guess the directory where to expect the architecture dependent native library of a specified package
#' e.g. for the package rClr, ${R_HOME}/library/rClr/libs/x64
#' This is a utility that is not specific to the rClr package
#'
#' @param pkgName the name of a package, e.g. 'rClr'
#' @return the prospective path in which a native library would be found, e.g. c:/R/library/rClr/libs/x64
#' @export
getNativeLibsPath <- function(pkgName) {
r_arch=Sys.getenv("R_ARCH")
arch <- sub( '/', '', r_arch)
file.path(getLibsPath(pkgName), arch)
#rlibs <- getNativeLibsPathRlibs(pkgName)
#rhome <- getNativeLibsPathRhome(pkgName)
#ifelse(file.exists(rlibs), rlibs, rhome)
}
#' Get the type code for a SEXP
#'
#' Get the type code for a SEXP, as returned by the TYPEOF macro
#'
#' @param sexp an R object
#' @return the type code, an integer, as defined in Rinternals.h
#' @export
getSexpType <- function(sexp) {
extPtr <-.External("r_get_sexp_type", sexp, PACKAGE=nativePkgName)
return(mkClrObjRef(extPtr))
}
#' Peek into the structure of R objects 'as seen from C code'
#'
#' Inspect one or more R object to get information on its representation in the engine.
#' This function is mostly useful for R/rClr developers. It is derived from the 'showArgs'
#' example in the R extension manual
#'
#' @param ... one or more R objects
#' @return NULL. Information is printed, not returned.
#' @export
inspectArgs <- function(...) {
extPtr <-.External("r_show_args", ..., PACKAGE=nativePkgName)
# return(mkClrObjRef(extPtr))
}
#' Get the COM variant type of a CLR object
#'
#' Get the COM variant type of a CLR object, e.g. "VT_ARRAY | VT_I8". This function only works when run on the Microsoft implementation of the CLR.
#' This function is useful for advanced diagnosis; most users should never have to use it.
#'
#' @param objOrType a CLR object, or type name, possibly namespace and assembly qualified type name, e.g. 'My.Namespace.MyClass,MyAssemblyName'.
#' @param methodName the name of the method called on the object or class specified with objOrType
#' @param ... one or more arguments to pass to the function call
#' @examples
#' \dontrun{
#' library(rClr)
#' cTypename <- "Rclr.TestCases"
#' # public static bool IsTrue(bool arg)
#' clrVT(cTypename, 'IsTrue', TRUE)
#' clrVT('System.Convert', 'ToInt64', 123L)
#' clrVT('System.Convert', 'ToUInt64', 123L)
#' }
#' @return A string
#' @export
clrVT <- function(objOrType, methodName, ...) {
if(nativePkgName!='rClrMs') {stop("The CLR is not Microsoft's. This function is CLR specific")}
return(clrCallStatic('Rclr.DataConversionHelper', 'GetReturnedVariantTypename',objOrType, methodName, ...))
# return(mkClrObjRef(extPtr))
}
#' Gets the type of a CLR object resulting from converting an R object
#'
#' Gets the type of a CLR object resulting from converting an R object. This function is mostly for documentation purposes, but may be of use to end users.
#'
#' @param x An R objects
#' @return A list, with columns including mode, type,class,length and the string of the corresponding CLR type.
#' @export
rToClrType <- function(x) {
list(
# what = str(x),
mode = mode(x),
type = typeof(x),
class = class(x),
length=length(x),
clrType = clrCallStatic('Rclr.ClrFacade', 'GetObjectTypeName', x)
)
}
#' Gets the type of a CLR object given its type name
#'
#' Gets the type of a CLR object given its type name
#'
#' @param objOrTypename a character vector of length one. It can be the full file name of the assembly to load, or a fully qualified assembly name, or as a last resort a partial name.
#' @return the CLR Type.
#' @export
clrGetType <- function(objOrTypename) {
if(is.character(objOrTypename))
return(clrCallStatic(clrFacadeTypeName, 'GetType',objOrTypename))
else if('cobjRef' %in% class(objOrTypename))
return(clrCall(objOrTypename, 'GetType'))
else
stop('objOrTypename is neither a cobjRef object nor a character vector')
}
#' Create a reference object wrapper around a CLR object
#'
#' (EXPERIMENTAL) Create a reference object wrapper around a CLR object
#'
#' @param obj an object of S4 class clrObj
#' @param envClassWhere environment where the new generator is created.
#' @return the reference object.
clrCobj <- function(obj, envClassWhere=.GlobalEnv) {
refgen <- setClrRefClass(obj@clrtype, envClassWhere)
refgen$new(ref=obj)
}
#' Create reference classes for an object hierarchy
#'
#' EXPERIMENTAL Create reference classes for an object hierarchy. Gratefully acknowledge Peter D. and its rJavax work.
#'
#' @param typeName a CLR type name, recognizable by clrGetType
#' @param env environment where the new generator is created.
#' @return the object generator function
setClrRefClass <- function(typeName,
env=topenv(parent.frame()))
{
isAbstract <- function(type) { clrGet(type, 'IsAbstract' ) }
isInterface <- function(type) { clrGet(type, 'IsInterface' ) }
tryCatch(getRefClass(typeName),
error=function(e) {
type <- clrGetType(typeName)
if(is.null(type)) stop(paste('CLR type not found for type name', typeName))
baseType <- clrGet(type, 'BaseType')
baseTypeName <- NULL
if (!is.null(baseType)) {
baseTypeName <- clrGet(baseType, 'FullName')
setClrRefClass(baseTypeName, env)
}
# interfaces <- Map(function(interface) interface$getName(),
# as.list(class$getInterfaces()))
# If the type is the type for an interface, then GetInterfacesFullnames will not return 'itself', so no need to deal with infinite recursion here.
interfaces <- clrCallStatic(reflectionHelperTypeName, 'GetInterfacesFullnames', type)
for (ifname in interfaces)
setClrRefClass(ifname, env)
## sort the interfaces lexicographically to avoid inconsistencies
contains <- c(baseTypeName,
sort(as.character(unlist(interfaces))))
## if an interface or an abstract type, need to contain VIRTUAL
if (isInterface(type) || isAbstract(type))
contains <- c(contains, "VIRTUAL")
declaredMethods <- clrCallStatic(reflectionHelperTypeName, 'GetDeclaredMethodNames', type)
# Map(function(method) method$getName(),
# Filter(notProtected, as.list(class$getDeclaredMethods())))
declaredMethods <- unique(declaredMethods)
methods <- sapply(as.character(declaredMethods), function(method) {
eval(substitute(function(...) {
arguments <- Map(function(argument) {
if (is(argument, 'System.Object')) {
argument$ref
} else
argument
}, list(...))
'TODO Here there should be the method description'
do.call(clrCall, c(.self$ref, method, arguments))
}, list(method=method)))
})
if (typeName == "System.Object")
setRefClass("System.Object",
fields = list(ref = 'cobjRef'),
methods = c(methods,
initialize = function(...) {
argu <- list(...)
x <- argu[['ref']]
if(!is.null(x)) {
ref <<- x
} else {
ref <<- clrNew(class(.self), ...)
}
.self
# },
# copy = function(shallow = FALSE) {
# ## unlike clone(), this preserves any
# ## fields that may be present in
# ## an R-specific subclass
# x <- callSuper(shallow)
# x$ref <- ref$clone()
# x
}),
contains = contains,
where = env)
else setRefClass(typeName,
methods = methods,
contains = contains,
where = env)
})
}