在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
相关产品推荐
相关产品推荐

