You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu下R调用含uthash的C共享库时dyn.load报undefined symbol错误

解决R加载C共享库时的undefined symbol: memoryMap错误

你遇到的错误根源是:代码中仅用extern声明了memoryMap变量,但未实际定义并初始化它。extern仅告知编译器“该变量在别处存在”,但你的代码没有为其分配内存,导致链接器生成的共享库中该符号未定义,R加载时无法找到对应实现。

解决方案

  1. 移除extern关键字,直接定义并初始化memoryMap为NULL(uthash要求哈希表指针必须初始化为NULL才能正常工作)
  2. 补充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;
}

编译与测试步骤

  1. 将修改后的代码保存为example.c
  2. 执行编译命令:
    R CMD SHLIB example.c
    
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:55:31