我正在尝试使用 Rcpp 在 R 中运行 C 代码,但不确定如何转换用于保存文件数据的缓冲区。在下面的第三行代码中,我分配了一个 unsigned char 缓冲区,我的问题是我不知道要使用什么 Rcpp 数据类型。将数据读入缓冲区后,我想出了如何使用 Rcpp::NumericMatrix 来保存最终结果,而不是字符缓冲区。我已经看到 Dirk Eddelbuettel 对类似问题的几个回答,他建议用 Rcpp 初始化命令替换所有“malloc”调用。我尝试使用 Rcpp::CharacterVector,但最后在循环中存在类型不匹配:Rcpp::CharacterVector 无法读取为 unsigned long long int。该代码为某些 C 编译器运行,但为其他编译器抛出“内存损坏”错误,
FILE *fp = fopen( filename, "r" );
fseek( fp, index_data_offset, SEEK_SET );
unsigned char* buf = (unsigned char *)malloc( 3 * number_of_index_entries * sizeof(unsigned long long int) );
fread( buf, sizeof("unsigned long long int"), (long)(3 * number_of_index_entries), fp );
fclose( fp );
// Convert "buf" into a 3-column matrix.
unsigned long long int l;
Rcpp::NumericMatrix ToC(3, number_of_index_entries);
for (int col=0; col<number_of_index_entries; col++ ) {
l = 0;
int offset = (col*3 + 0)*sizeof(unsigned long long int);
for (int i = 0; i < 8; ++i) {
l = l | ((unsigned long long int)buf[i+offset] << (8 * i));
}
ToC(0,col) = l;
l = 0;
offset = (col*3 + 1)*sizeof(unsigned long long int);
for (int i = 0; i < 8; ++i) {
l = l | ((unsigned long long int)buf[i+offset] << (8 * i));
}
ToC(1,col) = l;
l = 0;
offset = (col*3 + 2)*sizeof(unsigned long long int);
for (int i = 0; i < 8; ++i) {
l = l | ((unsigned long long int)buf[i+offset] << (8 * i));
}
ToC(2,col) = l;
}
return( ToC );
Run Code Online (Sandbox Code Playgroud)
C 和 C++ 可以很可爱。如果您知道自己在做什么,那么您就可以非常直接地了解底层硬件和用于高效推理的更高级别的抽象。
我建议简化和减少问题。从一个简单且已知的案例开始,例如 的 STL 向量double。让我们称之为x。用 10 或 100 个元素填充它,然后打开 aFILE并从中写入一个 blob
x.data(), x.size() * sizeof(double)
Run Code Online (Sandbox Code Playgroud)
关闭文件。通过第一次分配一个在读入RCPPNumericVector v同样大小的,然后读取的字节后面再打电话memcpy来&(v[0])。
它应该是相同的向量。
然后你可以推广到不同的类型。 因为向量保证是连续的内存,所以你可以直接使用这个序列化技巧。
您可以使用字符缓冲区对此进行更改,或者void*,或者...只要您小心不要不匹配,这些都不重要。即不要将int有效载荷分配给 adouble等等。
现在,有推荐的吗?地狱不,除非您追求性能并且足够了解您在做什么,在这种情况下这是合理的。否则,依靠出色的现有软件包(如fst或qs) 为您完成。
我希望这对您的问题有所帮助。我并不完全是什么那是你问。如果没有,也许你会澄清(并可能缩短/聚焦)它。
| 归档时间: |
|
| 查看次数: |
64 次 |
| 最近记录: |