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

如何从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:10:24