JSI绑定Native模块时为什么拿不到正确的方法?

闲人梦幻 阅读 122

我用JSI写了个Native模块,在C++层注册了函数,但JS端调用时报错说方法不存在。明明名字对上了,也重新编译了,还是不行。

我试过在installJSIBindings里打印日志,能进到函数里,但绑定的函数就是没挂到global上。是不是漏了什么步骤?

// jsi-bindings.cpp 里这样注册的
auto testFunc = jsi::Function::createFromHostFunction(
  runtime,
  jsi::PropNameID::forAscii(runtime, "testFunc"),
  0,
  [](jsi::Runtime& rt, const jsi::Value& thisVal, const jsi::Value* args, size_t count) -> jsi::Value {
    return jsi::String::createFromUtf8(rt, "hello from native");
  }
);
runtime.global().setProperty(rt, "testFunc", std::move(testFunc));
我来解答 赞 12 收藏
二维码
手机扫码查看
2 条解答
Good“玉研
问题很可能是 PropNameID 的创建方式。字符串生命周期没管理好的话,JSI 内部拿到的可能是野指针。

改一下试试:

auto propName = jsi::PropNameID::forAscii(runtime, "testFunc", 9);  // 显式传长度
auto testFunc = jsi::Function::createFromHostFunction(
runtime,
propName,
0, [](jsi::Runtime& rt, const jsi::Value& thisVal, const jsi::Value* args, size_t count) -> jsi::Value {
return jsi::String::createFromUtf8(rt, "hello from native");
}
);
runtime.global().setProperty(runtime, "testFunc", std::move(testFunc));


或者用 String 的方式更稳:

jsi::String funcName = jsi::String::createFromUtf8(runtime, "testFunc");
auto propName = jsi::PropNameID::forString(runtime, funcName);


还有个常见坑:如果你的模块在 iOS 上用 Swift 写的但底层用了 C++ JSI,桥接层可能没正确传递 runtime 对象。这种情况建议直接看 RN 官方那个 NativeModule 的 JSI 示例,代码结构基本是固定的。

如果还不行,打印一下 runtime.global().hasProperty(rt, "testFunc") 看看是不是 setProperty 本身失败了。
点赞
2026-03-18 18:00
小英杰
小英杰 Lv1
你的问题在于直接操作global在现代React Native里已经不太对路了。

新架构下正确的做法是用 jsi::Object 创建一个宿主对象,然后用 makeNativeBinding 绑定:

// 先定义一个结构体包装你的函数
struct TestModule {
std::string testFunc(jsi::Runtime& rt) {
return "hello from native"; }
};

// 然后这样绑定
auto testModule = jsi::Object::createFromHostObject(rt, std::make_shared());
runtime.global().setProperty(rt, "NativeTestModule", std::move(testModule));


或者更标准的做法是通过TurboModule注册,别直接挂global上。你得确认下:

1. 你是在哪个React Native版本?如果是0.68+,新架构的话得用TurboModule那一套
2. 检查你的C++代码是否链接正确,有时候编译过了但实际没加载到
3. 看看有没有用 RCT_EXTERN_MODULE + RCT_EXTERN_METHOD 这套暴露给JS

还有个小坑:如果你的函数签名是void返回的,得确保JSI侧和JS侧类型匹配。

你那个打印日志能进到installJSIBindings,说明C++确实执行了,那大概率就是绑定位置或方式的问题。贴一下你完整的注册代码,我看看具体哪儿的写法不对。
点赞
2026-03-11 06:02