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

在R中调用tdjson C库无返回值问题求助

解决R调用tdjson库时返回参数回显的问题

我正在为tdjson这个C库编写简单的R绑定,该库支持多语言直接调用。已经编译得到可用的libtdjson.so,且在Python中测试通过,但在R中调用时,函数仅返回原调用参数的列表,没有有效结果。

Python参考实现

from ctypes import *
import json

# load shared library
tdjson_path = "tdlib/lib/libtdjson.so"
tdjson = CDLL(tdjson_path)

_td_execute = tdjson.td_execute
_td_execute.restype = c_char_p
_td_execute.argtypes = [c_char_p]

def td_execute(query):
    query = json.dumps(query).encode('utf-8')
    result = _td_execute(query)
    if result:
        result = json.loads(result.decode('utf-8'))
    return result

# test TDLib execute method
test_command = {'@type': 'getTextEntities', 
                'text': '@telegram /test_command https://telegram.org telegram.me', 
                '@extra': ['5', 7.0, 'a']}

td_execute(test_command)

我尝试的R代码

library(jsonlite)

dyn.load("tdlib/lib/libtdjson.so", type = "External")

td_execute <- function(query) {
  query <- jsonlite::toJSON(query, auto_unbox = T)
  result <- .C("td_execute", charToRaw(query))
  return(result)
}

test_command = list("@type"="getTextEntities",
                    "text"="@telegram /test_command https://telegram.org telegram.me",
                    "@extra"= c("5", 7.0, 'a'))

t <- td_execute(test_command)
rawToChar(t[[1]])
# t only contains the original JSON string

问题原因与解决方案

问题根源

使用.C()函数调用tdjson的td_execute是错误的:

  • .C()会按值传递参数,默认将输入参数原样返回,无法正确获取C函数的返回值
  • td_execute的设计是返回一个char*类型的JSON字符串,而非通过修改传入参数输出结果

修正后的R代码

library(jsonlite)

# 加载共享库
dyn.load("tdlib/lib/libtdjson.so", type = "External")

td_execute <- function(query) {
  # 转换查询为符合要求的JSON字符串
  query_json <- jsonlite::toJSON(query, auto_unbox = TRUE)
  query_raw <- charToRaw(query_json)
  
  # 使用.Call()调用C函数,获取返回的字符串指针
  result_ptr <- .Call("td_execute", query_raw)
  
  if (!is.null(result_ptr)) {
    # 转换为R字符并解析JSON
    result_str <- rawToChar(result_ptr)
    # 调用tdjson的内存释放函数,避免内存泄漏
    .Call("td_json_client_free", result_ptr)
    return(jsonlite::fromJSON(result_str))
  } else {
    return(NULL)
  }
}

# 测试命令
test_command <- list(
  "@type" = "getTextEntities",
  "text" = "@telegram /test_command https://telegram.org telegram.me",
  "@extra" = c("5", 7.0, "a")
)

# 执行测试并打印结果
result <- td_execute(test_command)
print(result)

关键说明

  • 用.Call()替代.C():.Call()能直接获取C函数的返回值,适配td_execute的返回类型设计
  • 内存管理:必须调用td_json_client_free释放tdjson返回的字符串内存,否则会造成R进程的内存泄漏
  • JSON转换一致性:保持auto_unbox = TRUE,和Python代码行为一致,避免嵌套数组导致tdjson无法正确解析查询

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:15:54