如何从NativeCall导出函数返回Raku Hash对象?
在C中创建Raku Hash并通过NativeCall返回
核心思路
要实现从C函数返回Raku Hash,确实需要借助MoarVM的C API——因为Raku的核心运行时是MoarVM,所有内置类型(包括Hash)都由MoarVM的对象系统管理。你需要调用MoarVM提供的API来创建Hash、添加键值对,最后返回对应的MoarVM对象。
具体实现步骤
1. 编写C代码(依赖MoarVM头文件)
确保编译环境能访问MoarVM的头文件(通常随Raku安装附带,路径类似/usr/lib/raku/include/moarvm/)。以下是接收字符串并返回Hash的示例代码:
#include "moarvm.h" // 接收Raku字符串,处理后返回Raku Hash MVMObject* process_string_to_hash(MVMThreadContext *tc, MVMString *input_str) { // 创建空的Raku Hash实例 MVMObject* hash = MVM_hash_create(tc, tc->instance->boot_types.BOOTHash); // 处理输入字符串:示例将输入作为键,字符串长度作为值 // 把MoarVM字符串转成C字符串用于处理 char *c_input = MVM_string_utf8_encode_C_string(tc, input_str); MVMint64 str_length = MVM_string_graphs(tc, input_str); // 创建Hash的键(转成MVMString类型) MVMString* key = MVM_string_utf8_decode(tc, tc->instance->VMString, c_input, strlen(c_input)); // 创建Hash的值(将长度转成字符串类型) char len_buf[32]; snprintf(len_buf, sizeof(len_buf), "%"PRId64, str_length); MVMString* value = MVM_string_utf8_decode(tc, tc->instance->VMString, len_buf, strlen(len_buf)); // 向Hash中存入键值对 MVM_hash_at_put_str(tc, (MVMHash*)hash, key, value); // 释放临时分配的C字符串 MVM_free(c_input); // 返回Hash对象 return hash; }
2. 编译为共享库
假设C文件名为hash_utils.c,根据系统执行对应的编译命令:
# Linux/macOS gcc -shared -fPIC -o libhashutils.so hash_utils.c -I/usr/lib/raku/include/moarvm/ -L/usr/lib/raku/lib/ -lmoar # Windows(MinGW环境) gcc -shared -o hashutils.dll hash_utils.c -IC:/raku/include/moarvm/ -LC:/raku/lib/ -lmoar
3. 在Raku中用NativeCall绑定调用
编写Raku脚本,绑定C函数并测试功能:
use NativeCall; # 绑定C函数:注意参数类型和返回类型 sub process_string_to_hash(OpaquePointer, Str) returns Hash is native('./libhashutils.so') { * } # 获取MoarVM的线程上下文(C函数需要这个参数) my $tc = nqp::getcurrentthreadctx(); # 调用函数并输出结果 my $result = process_string_to_hash($tc, "Hello Raku NativeCall!"); say $result; # 输出:{Hello Raku NativeCall! => 23}
关键细节说明
- MVMThreadContext:MoarVM的线程上下文,几乎所有MoarVM API都需要这个参数,Raku中可通过
nqp::getcurrentthreadctx()直接获取。 - MVMString:Raku字符串在MoarVM中的底层表示,NativeCall会自动将Raku的
Str类型映射为C中的MVMString*。 - Hash操作API:
MVM_hash_create用于创建空Hash,MVM_hash_at_put_str用于添加字符串类型的键值对,还有其他重载函数支持不同类型的键值。 - 内存管理:MoarVM的垃圾回收会自动管理Hash和内置字符串对象,你只需要手动释放自己分配的临时C内存(比如示例中的
MVM_free(c_input))。
内容的提问来源于stack exchange,提问作者Rawley Fowler
相关产品推荐
相关产品推荐

