Ubuntu下R调用含uthash的C共享库时dyn.load报undefined symbol错误
解决R加载C共享库时的
undefined symbol: memoryMap错误 你遇到的错误根源是:代码中仅用extern声明了memoryMap变量,但未实际定义并初始化它。extern仅告知编译器“该变量在别处存在”,但你的代码没有为其分配内存,导致链接器生成的共享库中该符号未定义,R加载时无法找到对应实现。
解决方案
- 移除
extern关键字,直接定义并初始化memoryMap为NULL(uthash要求哈希表指针必须初始化为NULL才能正常工作) - 补充
example_R函数的返回值(原代码无返回逻辑,会导致编译警告或运行错误)
修改后的完整代码
#include <R.h> #include <Rinternals.h> #include "uthash.h" typedef struct { // 指向已分配内存的指针 void * ptr; // uthash内部使用的句柄 UT_hash_handle hh; } AllocatedMemory; // 定义并初始化哈希表指针(替代原extern声明) AllocatedMemory * memoryMap = NULL; static inline void* CALLOC(size_t n, size_t sz) { void * ptr = calloc(n, sz); if (ptr == NULL) error("Out of memory!"); AllocatedMemory * m = calloc(1, sizeof(AllocatedMemory)); m->ptr = ptr; HASH_ADD_PTR(memoryMap, ptr, m); return ptr; } SEXP example_R(SEXP vec_R) { unsigned int n = length(vec_R); unsigned int * v = CALLOC(n, sizeof(unsigned int)); // 示例:将输入向量的值复制到分配的内存(保证函数完整性) for (unsigned int i = 0; i < n; i++) { v[i] = INTEGER(vec_R)[i]; } // 创建并返回结果向量(必须补充返回值,否则会触发运行错误) SEXP res = PROTECT(allocVector(INTSXP, n)); memcpy(INTEGER(res), v, n * sizeof(unsigned int)); UNPROTECT(1); // 提示:实际场景中需添加内存清理逻辑,比如在R包的.onUnload中遍历哈希表释放内存 return res; }
编译与测试步骤
- 将修改后的代码保存为
example.c - 执行编译命令:
R CMD SHLIB example.c - 在R中加载并测试:
dyn.load("example.so") # 调用C函数测试 result <- .Call("example_R", 1:5) print(result) # 卸载共享库 dyn.unload("example.so")
额外说明
- 若
memoryMap需要在多个源文件中共享,可在一个文件中定义(如上述代码),其他文件用extern声明;单文件场景下直接定义即可。 - 建议添加内存清理逻辑,避免长期运行导致内存泄漏,例如在R包的
.onUnload函数中遍历哈希表释放所有已分配内存。
内容的提问来源于stack exchange,提问作者m.taheri
相关产品推荐
相关产品推荐

