Calling C code from R an introduction_第1页
Calling C code from R an introduction_第2页
Calling C code from R an introduction_第3页
Calling C code from R an introduction_第4页
Calling C code from R an introduction_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Calling C code from Ran introductionSigal BlayDept. of Statistics and Actuarial ScienceSimon Fraser UniversityOctober 2004Motivation: Speed Efficient memory management Using existing C librariesThe following functions provide a standard interface to compiled code that has been linked into R: .C .Cal

2、l .ExternalWe will explore using .C and .Call with 7 code examples:Using .CI. Calling C with an integer vectorII. Calling C with different vector typesUsing .CallIII. Sending R integer vectors to CIV. Sending R character vectors to CV. Getting an integer vector from CVI. Getting a character vector f

3、rom CVII. Getting a list from CAnd lastly, tips on creating an R package with compiled codeI.Calling C with an integer vector using .C /* useC1.c */void useC(int *i) i0 = 11;The C function should be of type void. The compiled code should not return anything except through its arguments.To compile th

4、e c code, type at the command prompt:The compiled code file name is In R: dyn.load(useC1.so)dyn.load(useC1.so) a a 1 1 2 3 4 5 6 7 8 9 10 out a 1 1 2 3 4 5 6 7 8 9 10 out$bout$b 1 11 2 3 4 5 6 7 8 9 10 You have to allocate memory to the vectors passed to .C in R by creating vectors of the right leng

5、th. The first argument to .C is a character string of the C function name. The rest of the arguments are R objects to be passed to the C function. All arguments should be coerced to the correct R storage mode to prevent mismatching of types that can lead to errors. .C returns a list object. The seco

6、nd .C argument is given the name b. This name is used for the respective component in the returned list object (but not passed to the compiled code).II.Calling C with different vector typesusing .C/* useC2.c */void useC(int *i, double *d, char *c, int *l) i0 = 11; d0 = 2.333; c1 = g; l0 = 0;To compi

7、le the c code, type at the command prompt: to get To compile more than one c file:to get In R: dyn.load(useC2.so) i d c l i 1 1 2 3 4 5 6 7 8 9 10 d c 1 a b c l 1 TRUE FALSE out out$i1 1 11 2 3 4 5 6 7 8 9 10$d1$c1 1 a g c“$l1 1 FALSE FALSE Other R objects can be passed to .C but it is better to use

8、 one of the other interfaces. With .C, the R objects are copied before being passed to the C code, and copied again to an R list object when the compiled code returns. Neither .Call nor .External copy their arguments. You should treat arguments you receive through these interfaces as read-only.Advan

9、tages to using .Call() instead of .C()(Posted by Prof Brian Ripley on R-help, Jun 2004)1) A lot less copying.2) The ability to dimension the answer in the C code.3) Access to other types, e.g. expressions, raw type and the ability to easily execute R code (call_R is a pain).4) Access to the attribut

10、es of the vectors, for example the names.5) The ability to handle missing values easily.III.Sending R integer vectors to Cusing .Call/* useCall1.c */#include #include SEXP getInt(SEXP myint, SEXP myintVar) int Imyint, n; / declare an integer variable int *Pmyint; / pointer to an integer vector PROTE

11、CT(myint = AS_INTEGER(myint); Rdefines.h is somewhat more higher level then Rinternal.h, and is preferred if the code might be shared with S at any stage. SEXP stands for Simple EXPression myint is of type SEXP, which is a general type, hence coercion is needed to the right type. R objects created i

12、n the C code have to be reported using the PROTECT macro on a pointer to the object. This tells R that the object is in use so it is not destroyed. Imyint = INTEGER_POINTER(myint)0; Pmyint = INTEGER_POINTER(myint); n = INTEGER_VALUE(myintVar); printf(“ Printed from C: n“); printf(“ Imyint: %d n, Imy

13、int); printf(“ n: %d n, n); printf(“ Pmyint0, Pmyint1: %d %d n, Pmyint0, Pmyint1); UNPROTECT(1); return(R_NilValue); The protection mechanism is stack-based, so UNPROTECT(n) unprotects the last n objects which were protected. The calls to PROTECT and UNPROTECT must balance when the users code return

14、s. to work with real numbers, replace int with double and INTEGER with NUMERIC In R: dyn.load(useCall1.so) myint out outNULLIV.Reading an R character vector from Cusing .Call/* useCall2.c */#include #include SEXP getChar(SEXP mychar) char *Pmychar5; / array of 5 pointers / to character strings PROTE

15、CT(mychar = AS_CHARACTER(mychar); / allocate memory:Pmychar0 = R_alloc(strlen(CHAR(STRING_ELT(mychar, 0), sizeof(char); Pmychar1 = R_alloc(strlen(CHAR(STRING_ELT(mychar, 1), sizeof(char); / . and copy mychar to Pmychar: strcpy(Pmychar0, CHAR(STRING_ELT(mychar, 0); strcpy(Pmychar1, CHAR(STRING_ELT(my

16、char, 1); printf(“ Printed from C:); printf(“ %s %s n,Pmychar0,Pmychar1); UNPROTECT(1); return(R_NilValue); In R: dyn.load(useCall2.so) mychar out - .Call(getChar, mychar)Printed from C: do reV.Getting an integer vector from Cusing .Call/* useCall3.c */#include #include SEXP setInt() SEXP myint; int

17、 *p_myint; int len = 5; / Allocating storage space: PROTECT(myint = NEW_INTEGER(len); p_myint = INTEGER_POINTER(myint); p_myint0 = 7; UNPROTECT(1); return myint;/ to work with real numbers, replace / int with double and INTEGER with NUMERICIn R: dyn.load(useCall3.so) out out1 7 0 0 0 0VI.Getting a c

18、haracter vector from Cusing .Call/* useCall4.c */#include #include SEXP setChar() SEXP mychar; PROTECT(mychar = allocVector(STRSXP, 5); SET_STRING_ELT(mychar, 0, mkChar(A); UNPROTECT(1); return mychar;In R: dyn.load(useCall4.so) out out1 A VII.Getting a list from Cusing .Call/* useCall5.c */#include

19、 #include SEXP setList() int *p_myint, i; double *p_double; SEXP mydouble, myint, list, list_names; char *names2 = integer, numeric; / creating an integer vector: PROTECT(myint = NEW_INTEGER(5); p_myint = INTEGER_POINTER(myint); / . and a vector of real numbers: PROTECT(mydouble = NEW_NUMERIC(5); p_

20、double = NUMERIC_POINTER(mydouble); for(i = 0; i 5; i+) p_doublei = 1/(double)(i + 1); p_myinti = i + 1; / Creating a character string vector / of the names attribute of the/ objects in out list: PROTECT(list_names = allocVector(STRSXP,2); for(i = 0; i dyn.load(useCall5.so) out out$integer1 1 2 3 4

21、5$numericIf you are developing an R package:copy to myPackage/src/ The user of the package will not have tomanually load the compiled c code with dyn.load(), so: add file to myPackage/R should contain the following code: .First.lib -function (lib, pkg) library.dynam(myPackage, pkg, lib) If you are developing an R package (cont.),modify the .C call: After the argument list to the C function, add PACKAGE=compiled_file.For example, if your compiled C code file name is , type: .C(useC, b = eger(a), PACKAGE=useC1) If you

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论