Lambda未指定捕获默认值导致变量无法隐式捕获的JNI代码问题
解决JNI中Lambda捕获变量的问题
嘿,我来帮你搞定这个Lambda捕获的错误!你遇到的问题核心是:在for_each里使用的Lambda函数没有明确捕获外部的a和b变量,导致编译器无法识别它们。咱们一步步来修正:
错误原因分析
你代码里的两个for_each Lambda都是用[]开头的,这意味着不捕获任何外部变量,但你在Lambda内部又试图修改a和b——这就导致了编译器报错"variable cannot be implicitly captured"。另外,你之前写的[](int a=0){};完全是多余的,a应该作为函数的局部变量来定义,而不是在Lambda里初始化。
修正方案
我们需要使用引用捕获来让Lambda访问并修改外部的a和b,因为我们需要在Lambda里改变这两个变量的值。有两种常用方式:
[&a]:只引用捕获a变量[&]:引用捕获所有外部变量(更简洁,适合这里的场景)
修改后的完整代码
#include <jni.h> #include <string> #include <iostream> #include <iomanip> #include <sstream> #include <algorithm> // 确保包含for_each所需的头文件 #include <cctype> // 用于toupper using namespace std; static int nameToNumber(string fn, string ln) { string nameOne = fn; string nameTwo = ln; int a = 0; // 正确定义变量a,删掉无用的Lambda初始化 int b = 0; int num = 0; // 第一个for_each:用[&]引用捕获外部变量,这里主要需要a for_each(nameOne.begin(), nameOne.end(), [&](char &c ) { c = ::toupper(c); switch (c){ case 'A': case 'J': case 'S': a += 1; break; case 'B': case 'K': case 'T': a += 2; break; case 'C': case 'L': case 'U': a += 3; break; case 'D': case 'M': case 'V': a += 4; break; case 'E': case 'N': case 'W': a += 5; break; case 'F': case 'O': case 'X': a += 6; break; case 'G': case 'P': case 'Y': a += 7; break; case 'H': case 'Q': case 'Z': a += 8; break; case 'I': case 'R': a += 9; break; default: break; // 加0可以省略,直接break } }); // 第二个for_each:同样用[&]引用捕获外部变量,这里主要需要b for_each(nameTwo.begin(), nameTwo.end(), [&](char &c) { c = ::toupper(c); switch (c){ case 'A': case 'J': case 'S': b += 1; break; case 'B': case 'K': case 'T': b += 2; break; case 'C': case 'L': case 'U': b += 3; break; case 'D': case 'M': case 'V': b += 4; break; case 'E': case 'N': case 'W': b += 5; break; case 'F': case 'O': case 'X': b += 6; break; case 'G': case 'P': case 'Y': b += 7; break; case 'H': case 'Q': case 'Z': b += 8; break; case 'I': case 'R': b += 9; break; default: break; } }); num = a + b; if ((num > 9) && (num != 11) && (num != 22) && (num != 33)) { a = num / 10; // 获取十位 b = num % 10; // 获取个位 num = a + b; } return num; } // 补充jstringToString和decToHexa的实现(假设你之前没写全) extern "C" JNIEXPORT jstring JNICALL Java_com_sezju_namenumerology_MainActivity_transformInfo( JNIEnv *env, jobject /* this */, jstring fName, jstring lName, jint age) { // 将JNI的jstring转换为std::string的工具函数 auto jstringToString = [env](jstring jstr) -> string { const char* cstr = env->GetStringUTFChars(jstr, nullptr); string str(cstr); env->ReleaseStringUTFChars(jstr, cstr); return str; }; // 将十进制转为十六进制字符串的工具函数 auto decToHexa = [](int num) -> string { stringstream ss; ss << hex << uppercase << num; return ss.str(); }; int luckynum = nameToNumber(jstringToString(fName), jstringToString(lName)); string message = jstringToString(fName) + " " + jstringToString(lName) + ".\n"; message += "You are " + decToHexa((int)age)+ " years old in hexadecimal. \n"; message += "Your number is " + std::to_string(luckynum) + " \n"; return env->NewStringUTF(message.c_str()); }
关键修改点说明
- 变量定义:删掉了无用的
[](int a=0){};,在函数开头正确初始化int a = 0; - Lambda捕获:两个
for_each的Lambda都用[&]来引用捕获外部变量,这样Lambda内部就能正常修改a和b了 - 代码简化:把
a=a+1改成更简洁的a +=1,默认分支的a=a+0可以直接省略,用break代替
这样修改后,你的代码就能正常运行,输入姓名后会得到预期的一位数或者11、22、33的结果啦!
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

