我正在学习使用C编程语言,并且可能遇到不兼容的指针类型返回的问题。
我有与由R读取为data.frame两列的文本文件。看完这个我想执行.CALL在C函数,将读取date.frame并试图返回值时将返回值R中的变量,但发生段错误错误。我找不到解决此问题的方法,有人可以帮助我吗?
文本文件分为两列,如下例所示。
Q0045 YJL166W
Q0045 YDL085W
Q0045 YDR119W-A
这是用于读取data.frame的C代码。
#include <Rinternals.h>
#include <Rdefines.h>
#include <R.h>
#include <stdlib.h>
#include <stdio.h>
char **test(SEXP lst){
int i,elLength;
int len = length(lst);
SEXP col1, col2;
char ***target = malloc(sizeof(char **) *len);
col1 = VECTOR_ELT(lst, 0);
col2 = VECTOR_ELT(lst, 1);
elLength = length(col1);
target[0] = malloc(sizeof(char *) * elLength);
target[1] = malloc(sizeof(char *) * elLength);
for (i=0; i<elLength; i++) {
target[0][i] = CHAR(STRING_ELT(col1, i));
target[1][i] = CHAR(STRING_ELT(col2, i));
}
return target;
}
此后,我在终端中使用命令行创建.so文件:
R CMD SHLIB test.c
最后,R中的代码读取文件并执行.Call。
dyn.load("/home/lab/test.so")
fileR = data.frame(read.table("file.txt", sep = "\t", stringsAsFactors = FALSE))
fileFromC = .Call("test", fileR)
之后,我从终端在R中运行错误:
*** caught segfault ***
address 0x310000c0, cause 'memory not mapped'
如果我只打印并返回R_NilValue误差不显示。但我需要C工艺的给新变量回归。
答案 0 :(得分:0)
malloc()
不是处理R扩展中内存分配的正确方法。
请查看R文档6.1 Memory allocation部分
6.1.1临时存储分配
在此,R将在对.C,.Call或.External的调用结束时回收内存。使用
char *R_alloc(size_t n, int size)
每个分配n个大小字节单位。
即您可以将此分配器用于要通过C API return
进行存储的内存。
答案 1 :(得分:0)
我可以使用下面的代码来完成所需的工作。感谢所有合作的人。
#include <Rinternals.h>
#include <Rdefines.h>
#include <R.h>
#include <stdlib.h>
#include <stdio.h>
char **stripList(SEXP lst){
int i, j, elLength;
int len = length(lst);
char *rans;
SEXP col1, col2;
char ***target = (char *) R_alloc(len, sizeof(char **));
col1 = VECTOR_ELT(lst, 0);
col2 = VECTOR_ELT(lst, 1);
elLength = length(col1);
SEXP ans = PROTECT(Rf_allocMatrix(STRSXP,elLength, len));
target[0] = malloc(sizeof(char *) * elLength);
target[1] = malloc(sizeof(char *) * elLength);
for (i=0; i<elLength; i++) {
target[0][i] = CHAR(STRING_ELT(col1, i));
target[1][i] = CHAR(STRING_ELT(col2, i));
}
for (int i = 0; i < elLength; i++) for (int j = 0; j < len; j++)
SET_STRING_ELT(ans, i + j * elLength, Rf_mkChar(target[j][i]));
UNPROTECT(1);
return ans;
}