You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在React-Native安卓应用中调用C语言函数?

在React Native中调用C库函数:可行方案与实现步骤

当然可以在React Native里调用C语言编写的库!我之前帮好几个开发者搞定过类似需求,核心思路是通过React Native的原生模块(Native Modules),结合Android的JNI(Java Native Interface)来实现JS层到C代码的桥接。下面我一步步给你讲清楚实现方法,还有基础测试环境的搭建步骤。

一、核心原理梳理

React Native的JS代码和Android原生层(Java/Kotlin)通过内置的桥接机制通信,而Android原生层可以通过JNI直接调用C/C++代码。所以整体流程是:

JS 调用 React Native原生模块 → 原生模块通过JNI调用C库函数 → 结果返回给JS层

二、基础测试环境搭建

首先确保你已经有一个能正常运行的React Native Android项目,然后补充以下环境:

  • Android Studio(用来处理JNI配置、C代码编译)
  • 你的C语言库文件(可以是.c/.cpp源码,也可以是预编译好的.so动态库)
  • 配置NDK与CMake:打开Android Studio的SDK Manager,找到NDK (Side by side)CMake并安装

接下来做项目目录准备:

  • android/app/src/main/目录下创建jni文件夹,用来存放C源码和JNI配置文件
  • 如果用预编译的.so库,在android/app/src/main/创建jniLibs文件夹,按CPU架构分子目录(比如armeabi-v7aarm64-v8a),把对应架构的.so文件放入对应目录

三、具体实现步骤(以自定义C函数为例)

1. 编写测试C库代码

先写两个简单的C函数做测试,在android/app/src/main/jni/下创建native-lib.c文件:

#include <jni.h>
#include <string.h>

// JNI函数命名规则:Java_包名_原生模块类名_方法名
// 替换com_yourprojectname为你实际的Android项目包名
JNIEXPORT jstring JNICALL
Java_com_yourprojectname_MyNativeModule_getHelloFromC(JNIEnv *env, jobject thiz) {
    return (*env)->NewStringUTF(env, "Hello from C library!");
}

// 加法测试函数
JNIEXPORT jint JNICALL
Java_com_yourprojectname_MyNativeModule_addNumbers(JNIEnv *env, jobject thiz, jint a, jint b) {
    return a + b;
}

2. 创建React Native原生模块(Java层)

android/app/src/main/java/com/yourprojectname/目录下创建MyNativeModule.java(替换包名为你的实际包名):

package com.yourprojectname;

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

public class MyNativeModule extends ReactContextBaseJavaModule {
    // 加载C库,库名对应后续CMake配置的名字
    static {
        System.loadLibrary("native-lib");
    }

    // 声明JNI方法,和C代码里的函数对应
    public native String getHelloFromC();
    public native int addNumbers(int a, int b);

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

    @Override
    public String getName() {
        // 这个名字是JS层调用模块的标识,必须唯一
        return "MyNativeModule";
    }

    // 暴露给JS的方法,用@ReactMethod注解
    @ReactMethod
    public void getHelloFromC(Callback callback) {
        String result = getHelloFromC();
        callback.invoke(result); // 将结果返回给JS
    }

    @ReactMethod
    public void addNumbers(int a, int b, Callback callback) {
        int result = addNumbers(a, b);
        callback.invoke(result);
    }
}

3. 注册原生模块

在同目录下创建MyPackage.java,用来把原生模块注册到React Native:

package com.yourprojectname;

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 MyPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new MyNativeModule(reactContext));
        return modules;
    }

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

然后打开MainApplication.java,在getPackages()方法中添加这个包:

@Override
protected List<ReactPackage> getPackages() {
  List<ReactPackage> packages = new PackageList(this).getPackages();
  // 添加上自定义的Package
  packages.add(new MyPackage());
  return packages;
}

4. 配置CMake编译C源码(如果用源码编译)

android/app/src/main/jni/下创建CMakeLists.txt

cmake_minimum_required(VERSION 3.10.2)

# 项目名,随便取,和后面的库名对应即可
project("native-lib")

# 编译C源码为动态库
add_library(
        native-lib  # 库名,对应Java里System.loadLibrary的参数
        SHARED     # 编译为共享库
        native-lib.c) # 你的C源码文件

# 链接NDK的日志库,方便调试
find_library(
        log-lib
        log)

target_link_libraries(
        native-lib
        ${log-lib})

然后修改android/app/build.gradle,在android块中添加NDK和CMake配置:

android {
    // ...其他原有配置
    defaultConfig {
        // ...其他原有配置
        externalNativeBuild {
            cmake {
                cppFlags ""
                // 指定支持的CPU架构,按需选择
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/jni/CMakeLists.txt" // 指定CMake配置文件路径
            version "3.10.2" // 匹配你安装的CMake版本
        }
    }
}

5. 在JS层调用C库函数

打开你的React Native JS组件(比如App.js),通过NativeModules调用原生模块:

import { NativeModules } from 'react-native';

// 获取自定义的原生模块
const { MyNativeModule } = NativeModules;

// 调用C库的字符串返回函数
MyNativeModule.getHelloFromC((result) => {
  console.log('来自C库的消息:', result);
});

// 调用C库的加法函数
MyNativeModule.addNumbers(5, 3, (result) => {
  console.log('C库计算的加法结果:', result);
});

四、关键注意事项

  • 如果使用预编译的.so库,无需配置CMake,只需把.so放入jniLibs对应架构目录,然后在Java中调用System.loadLibrary("你的库名")即可。
  • JNI函数的命名必须严格遵循Java_包名_类名_方法名的规则,否则会出现找不到方法的错误,也可以用javah工具自动生成头文件来避免拼写错误。
  • 处理复杂数据类型(比如数组、结构体)时,需要在JNI层做类型转换,例如把JS数组转为C数组,处理完成后再转回JS可识别的类型。
  • 测试时,先执行cd android && ./gradlew assembleDebug编译Android项目,再回到根目录执行npx react-native run-android启动应用,就能在日志里看到C库返回的结果了。

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

火山引擎 最新活动