在 C++ lambda 表达式中捕获 JNIENV* 的错误

4

我在 Main.cpp 文件中有一个 JNI 调用,形如:

JNIEXPORT jstring   JNICALL
    Java_packagename_MainActivity_GenerateAlphabet(JNIEnv *env, jobject thiz)
        {
            generateAlphabet([](string letters, string numbers) {
                        return (env)->NewStringUTF("test");

            });
        }

但是这段代码给我报错:

jni/Main.cpp: 在 lambda 函数中:

jni/Main.cpp:86:33: 错误:未捕获 'env'

我真的需要在 lambda 函数中使用 env,有人能帮帮我吗。

编辑:

被接受的答案解决了这个问题,但请记住,你不能在 lambda 表达式中返回一个值。

2个回答

5

你可以使用 [env]env 放在捕获列表里。

但是,这是一个非常糟糕的想法。 捕获的 env 仅对特定线程有效。 如果您的 lambda 在不同的线程上被调用,则结果将无法定义。

您可以在lambda中捕获 JavaVM* 指针(从传递的 env 中获取),并使用 AttachCurrentThread 在lambda内检索相应的 env


除非你知道 generateAlphabet 做了什么(很可能它不涉及线程),否则你不能说这是一个坏主意。 - user253751
3
不要、不要、不要——绝对不要储存传递给函数的 env 指针,除非你喜欢在生产服务器上进行 3am 的调试并且只能使用少量 pdb 文件。请注意保持原意,使语言通俗易懂。 - Bathsheba
1
@Downvoter:如果我弄错了lambda语法,请告诉我。如果你不喜欢我对env的评论,那么我们就同意有异议。 - Bathsheba
你会创建一个线程本地变量来在std::sort的比较器中使用env吗?还是直接捕获它? - user253751
1
只要您在调用Java_packagename_MainActivity_GenerateAlphabet时保持在线程和堆栈帧内,您可以按任何您喜欢的方式使用传递的env。许多辅助类(字符串保护程序、数组保护程序)都利用了这一点。我认为更深入的讨论超出了这个问题的范围。 - Bathsheba
显示剩余2条评论

0
在C++中,您需要指定哪些变量可以在lambda表达式(也称为捕获)中访问。
开始的[]是一个空的捕获列表。只需在其中添加env以通过值捕获env
[env](string letters, string numbers) {
    return (env)->NewStringUTF("test");
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接