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

React Native集成C库遇Buck报错,求RN与C双向传参实现方案

我懂你现在的难处——没接触过Android开发,还要对接C语言的游戏引擎,选了React Native本来想靠NodeJS基础过渡,结果Buck工具先给你泼了冷水。先帮你理清Buck的问题,再给你一个更适合入门的方案:用React Native原生模块+Android NDK实现双向传参,上手更快,资料也更全。


先解决你的Buck错误

你执行的命令有几个明显的语法问题,这也是报错的原因:

  • mkdir buck-project cd buck-project是两个独立命令,需要分开执行:
    mkdir buck-project
    cd buck-project
    
  • buck project buck-project --ide intellij 语法错误,正确写法是buck project --ide intellij(不需要重复项目名)
  • buck installbuck-project 应该是buck install //your:target-name,而且你还没定义Buck的构建目标,自然会报“引用不存在的目录”

不过说实话,Buck的学习曲线对新手来说太陡了,尤其是你没有Android开发背景,不如用React Native官方支持的原生模块+NDK方案,下面是完整的入门示例:


入门示例:React Native与C代码双向传参

第一步:初始化React Native项目

先创建一个新的RN项目(已有项目可跳过):

npx react-native init RNCInteropDemo
cd RNCInteropDemo

第二步:创建Android原生模块(RN与C的中间层)

在android/app/src/main/java/com/rncinteropdemo/目录下创建以下文件:

1. CInteropModule.java(核心交互类)

package com.rncinteropdemo;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;

public class CInteropModule extends ReactContextBaseJavaModule {
    static {
        // 加载我们后续编译的C库
        System.loadLibrary("native-lib");
    }

    public CInteropModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        // RN中调用该模块的名称
        return "CInterop";
    }

    // RN调用C函数:传递字符串参数,获取返回值
    @ReactMethod
    public void callCFunction(String input, Callback callback) {
        String result = nativeProcessString(input);
        callback.invoke(null, result);
    }

    // C主动调用RN的方法:触发事件传递参数
    @ReactMethod
    public void triggerCToRNEvent(String message) {
        callRNFunction(getReactApplicationContext().getJNIEnv(), getReactApplicationContext(), message);
    }

    // 声明C函数(具体实现放在C文件中)
    public native String nativeProcessString(String input);
    public native void callRNFunction(JNIEnv env, jobject reactContext, jstring message);
}

2. CInteropPackage.java(注册模块)

package com.rncinteropdemo;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CInteropPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new CInteropModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

3. 注册Package到MainApplication.java

找到getPackages()方法,添加我们的包:

@Override
protected List<ReactPackage> getPackages() {
  List<ReactPackage> packages = new PackageList(this).getPackages();
  // 添加这一行
  packages.add(new CInteropPackage());
  return packages;
}

第三步:编写C代码实现业务逻辑

在android/app/src/main/目录下创建jni文件夹,然后创建以下文件:

1. native-lib.c(C代码核心)

#include <jni.h>
#include <string.h>
#include <android/log.h>

#define LOG_TAG "CInterop"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

// RN调用C:处理字符串并返回
JNIEXPORT jstring JNICALL
Java_com_rncinteropdemo_CInteropModule_nativeProcessString(JNIEnv *env, jobject thiz, jstring input) {
    const char *inputStr = (*env)->GetStringUTFChars(env, input, NULL);
    if (inputStr == NULL) {
        return NULL;
    }

    // 示例:给输入字符串添加前缀
    char result[100];
    snprintf(result, sizeof(result), "C代码处理结果:%s", inputStr);
    LOGD("收到RN传递的参数:%s", inputStr);

    // 释放JNI字符串资源
    (*env)->ReleaseStringUTFChars(env, input, inputStr);

    return (*env)->NewStringUTF(env, result);
}

// C主动调用RN:发送事件传递参数
JNIEXPORT void JNICALL
Java_com_rncinteropdemo_CInteropModule_callRNFunction(JNIEnv *env, jobject thiz, jobject reactContext, jstring message) {
    // 获取RN的事件发射器类
    jclass reactContextClass = (*env)->FindClass(env, "com/facebook/react/bridge/ReactApplicationContext");
    jmethodID getJSModuleMethod = (*env)->GetMethodID(env, reactContextClass, "getJSModule", "(Ljava/lang/Class;)Ljava/lang/Object;");
    jclass eventEmitterClass = (*env)->FindClass(env, "com/facebook/react/modules/core/DeviceEventManagerModule$RCTDeviceEventEmitter");
    jobject eventEmitter = (*env)->CallObjectMethod(env, reactContext, getJSModuleMethod, eventEmitterClass);

    // 调用RN的emit方法发送事件
    jmethodID emitMethod = (*env)->GetMethodID(env, eventEmitterClass, "emit", "(Ljava/lang/String;Ljava/lang/Object;)V");
    (*env)->CallVoidMethod(env, eventEmitter, emitMethod, (*env)->NewStringUTF(env, "CToRNEvent"), message);

    // 释放JNI资源
    (*env)->DeleteLocalRef(env, reactContextClass);
    (*env)->DeleteLocalRef(env, eventEmitterClass);
    (*env)->DeleteLocalRef(env, eventEmitter);
}

2. Android.mk(NDK编译配置)

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := native-lib
LOCAL_SRC_FILES := native-lib.c
LOCAL_LDLIBS    := -llog # 引入日志库,方便调试

include $(BUILD_SHARED_LIBRARY)

3. Application.mk(NDK平台配置)

APP_ABI := all # 编译所有架构的库
APP_PLATFORM := android-23 # 最低支持Android 6.0

第四步:配置NDK编译环境

打开android/build.gradle(项目根目录下的那个),在buildscript的ext中添加NDK版本(用你本地安装的版本即可):

buildscript {
    ext {
        buildToolsVersion = "33.0.0"
        minSdkVersion = 23
        compileSdkVersion = 33
        targetSdkVersion = 33
        ndkVersion = "25.1.8937393"
    }
    // 其他代码...
}

然后打开android/app/build.gradle,在android块中添加NDK编译配置:

android {
    // 其他代码...
    defaultConfig {
        // 其他代码...
        ndk {
            abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
        }
        externalNativeBuild {
            ndkBuild {
                path "src/main/jni/Android.mk"
            }
        }
    }
    // 添加externalNativeBuild块
    externalNativeBuild {
        ndkBuild {
            path "src/main/jni/Android.mk"
        }
    }
}

第五步:在RN中测试双向传参

修改App.js,实现调用C函数和监听C发送的事件:

import React, { useEffect, useState } from 'react';
import { View, Text, Button, NativeModules, DeviceEventEmitter } from 'react-native';

const { CInterop } = NativeModules;

const App = () => {
  const [cResult, setCResult] = useState('');
  const [cMessage, setCMessage] = useState('');

  // 调用C函数,传递参数并获取返回值
  const handleCallC = () => {
    CInterop.callCFunction('Hello from RN!', (error, res) => {
      if (error) console.error(error);
      else setCResult(res);
    });
  };

  // 触发C主动发送消息到RN
  const handleTriggerCEvent = () => {
    CInterop.triggerCToRNEvent('Hello from C!');
  };

  // 监听C发送的事件
  useEffect(() => {
    const listener = DeviceEventEmitter.addListener('CToRNEvent', (msg) => {
      setCMessage(msg);
    });
    return () => listener.remove();
  }, []);

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}>
      <Button title="调用C函数" onPress={handleCallC} />
      {cResult && <Text style={{ marginTop: 20 }}>{cResult}</Text>}
      
      <Button title="触发C主动发消息" onPress={handleTriggerCEvent} style={{ marginTop: 30 }} />
      {cMessage && <Text style={{ marginTop: 20, color: 'blue' }}>C主动推送:{cMessage}</Text>}
    </View>
  );
};

export default App;

第六步:运行项目

连接Android设备或启动模拟器,执行命令:

npx react-native run-android

现在你就能看到:点击第一个按钮,RN调用C函数并获取返回值;点击第二个按钮,C主动向RN发送消息,完美实现双向传参。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:40:29