如何在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-v7a、arm64-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




