Android Studio命令参数位置在哪?需在JNI中配置argc/argv调试.cpp路径
在Android Studio中为JNI配置argc/argv以设置调试路径
我明白你想在Android的JNI层模拟命令行参数(argc和argv)来传递输入输出路径,方便调试阴影移除功能。下面我会帮你梳理实现步骤,同时优化你现有的代码:
1. 修正JNI函数的参数传递逻辑
首先你的JNI函数签名存在问题——Java层没法直接传递int argc和char** argv。我们需要从Java层传入字符串数组,再在JNI层转换成argc/argv的形式:
Java层代码(MainActivity)
public class MainActivity extends AppCompatActivity { // 加载JNI库 static { System.loadLibrary("shadow-remove"); } // 声明JNI方法,接收路径字符串数组 public native int RemoveShadow(String[] args); // 调试调用示例 private void testShadowRemoval() { // 模拟命令行参数:argv[0]占位(对应程序名),argv[1]输入路径,argv[2]输出路径 String[] args = { "", "/sdcard/Documents/input.jpg", "/sdcard/Documents/output.jpg" }; int result = RemoveShadow(args); if (result != 0) { Log.e("ShadowRemoval", "阴影移除执行失败"); } } }
JNI层修正后的完整代码
#include <jni.h> #include <string> #include <iostream> #include <cstring> #include <opencv2/opencv.hpp> #include <omp.h> using namespace cv; using namespace std; class ShadowRemover { private: Mat* image; int width, height, channels; Mat* shadowMap; // 假设你已提前定义并初始化该变量 public: ShadowRemover(char* in) { image = new Mat(); ReadImage(*image, in); width = image->cols; height = image->rows; channels = image->channels(); } void RemoveShadow(char* out) { // 初始化多线程数据结构(OpenMP) int threadCount = omp_get_max_threads(); Mat* blockList = new Mat[threadCount]; for (int i = 0; i < threadCount; i++) { blockList[i] = Mat(height, width, CV_32FC3, Scalar(0, 0, 0)); } Mat dsMask = Mat(shadowMap->rows, shadowMap->cols, CV_8UC1, Scalar(0)); // 这里编写你的阴影移除核心逻辑... // 处理完成后保存输出图像 imwrite(out, *image); // 释放动态分配的资源 delete[] blockList; } // 实现图像读取功能 void ReadImage(Mat& img, char* path) { img = imread(path, IMREAD_COLOR); if (img.empty()) { cerr << "无法读取图像: " << path << endl; exit(-1); } } // 析构函数:避免内存泄漏 ~ShadowRemover() { delete image; delete shadowMap; } }; extern "C" JNIEXPORT jint JNICALL Java_com_example_admin_shadowdoctest_MainActivity_RemoveShadow(JNIEnv *env, jobject thiz, jobjectArray args) { // 获取参数数量 int argc = env->GetArrayLength(args); if (argc != 3) { cerr << "使用方式: [程序名] 输入路径 输出路径" << endl; return -1; } // 将Java字符串数组转换为char*数组(模拟argv) char** argv = new char*[argc]; for (int i = 0; i < argc; i++) { jstring jstr = (jstring)env->GetObjectArrayElement(args, i); const char* cstr = env->GetStringUTFChars(jstr, nullptr); // 复制字符串到堆内存,避免JNI释放后失效 argv[i] = new char[strlen(cstr) + 1]; strcpy(argv[i], cstr); // 释放JNI局部引用和字符串资源 env->ReleaseStringUTFChars(jstr, cstr); env->DeleteLocalRef(jstr); } // 执行阴影移除逻辑 ShadowRemover* sr = new ShadowRemover(argv[1]); sr->RemoveShadow(argv[2]); delete sr; // 释放argv的内存 for (int i = 0; i < argc; i++) { delete[] argv[i]; } delete[] argv; return 0; }
2. Android Studio中调试路径的配置
如果想在调试时灵活指定路径,你有两种选择:
- 硬编码调试路径:直接在Java层的
testShadowRemoval方法里写死测试用的SD卡路径(注意要申请READ_MEDIA_IMAGES/WRITE_EXTERNAL_STORAGE权限,Android 10+需适配分区存储)。 - 通过运行配置传递参数:
- 打开
Run/Debug Configurations - 选择你的App配置,切换到
Arguments标签 - 在
Program arguments中输入路径,比如/sdcard/input.jpg /sdcard/output.jpg - 在Java层读取参数并传递给JNI:
String[] args = getIntent().getStringArrayExtra("android.intent.extra.PROGRAM_ARGUMENTS");
- 打开
3. 关键注意事项
- 内存管理:JNI层的字符串和动态分配的内存必须手动释放,避免内存泄漏。
- 权限配置:在
AndroidManifest.xml中添加存储权限,并在运行时申请。 - OpenMP支持:要在
CMakeLists.txt中开启OpenMP:find_package(OpenMP REQUIRED) if(OpenMP_CXX_FOUND) target_link_libraries(shadow-remove PRIVATE OpenMP::OpenMP_CXX) endif() - OpenCV集成:确保已将OpenCV Android SDK正确配置到项目中。
内容的提问来源于stack exchange,提问作者Nattawan Daengdej
相关产品推荐
相关产品推荐

