使用 NDK 将选择循环应用程序移植到 Android。设计问题

发布于 2024-10-11 01:07:32 字数 758 浏览 5 评论 0原文

我有一个网络应用程序,它使用这样的选择循环:

bool shutdown=false;
while (!shutdown) {

     [do something]
     select(...,timeout);
}

主循环不能再在 Android 应用程序中像这样工作,因为应用程序需要接收意图,需要处理 GUI 等。

认为我基本上有三种可能性:

  1. 我 应用程序的 java 部分的主循环。
  2. 让循环在它自己的线程中运行并以某种方式与 java 进行通信。
  3. 螺丝 Android <= 2.3 并使用本机活动并使用 AInputQueue/ALooper 而不是 select。

第一种可能性并不容易,因为java没有适用于fds的select。在每次循环到 java 后简单地使用 select 和 return 也不是一个优雅的可能性,因为这需要将超时设置为 20ms 之类的值,以便在程序的 java 部分中获得良好的响应时间。

第二个概率听起来更好,但我已经在程序的 java 和 c++/c 部分之间进行了一些通信。冷工作的东西:

  1. 使用插座,有点丑。
  2. 在“java gui线程”中使用本机调用并在“c线程”中使用本机回调。两个线程都需要有线程安全的实现,但这是可以管理的。

我还没有探索第三种可能性,但我认为这不是可行的方法。

我想我可以把一些可行的东西组合在一起,但我问什么是最好的选择路径。

I have an network application which uses a select loop like this:

bool shutdown=false;
while (!shutdown) {

     [do something]
     select(...,timeout);
}

THe main loop cannot work like this in an Android application anymore since the application needs to receive Intents, need to handle GUI, etc.

I think I have basically three possibilities:

  1. Move the main loop to the java part of the application.
  2. Let the loop run in its own thread and somehow communicate from/to java.
  3. Screw Android <= 2.3 and use a native activity and use AInputQueue/ALooper instead of select.

The first possibility is not easy since java has no select which works on fds. Simply using the select and return after each loop to java is not an elegant possibility either since that requires setting the timeout to something like 20ms to have a good response time in the java part of the program.

The second probability sound nicer but I have do some communication between java and the c++/c part of the program. Things that cold work:

  1. Using a socket, kind of ugly.
  2. using native calls in the "java gui thread" and callback from native in the "c thread". Both threads need to have thread safe implementations but this is managable.

I have not explored the third possibility but I think that it is not the way to go.

I think I can hack something together which will work but I asking what is the best path to chose.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如痴如狂 2024-10-18 01:07:32

根据提供的有限信息,我可以想到以下方法:

循环可以在单独的线程中运行,有两个选项:
a) 查找 GUI 主导的更改(基于全局本机状态变量的值,例如枚举类型的 native_app_state)
b) 发生某些事情会触发对 Java 的回调

您可以使用单独的本机函数或一个集成的本机函数来响应来自 Java 的 GUI 事件 - 您可以在其中使用该全局本机状态变量的状态。

您可以根据每个状态中发生的情况以及应用程序的性能限制来优化实现。

Based on limited info provided, I can think of following approach:

A loop can run in a separate thread with two options:
a) look for gui led changes (based on value of a global native state variable say, native_app_state, of enum type)
b) something happens that triggers a callback to Java

You can have separate native functions or one integrated native function to respond to GUI events from Java - where you can use the state of that global native state variable.

You can optimize the implementation based on what happens in each state, and the performance constraints of the application.

那请放手 2024-10-18 01:07:32

也许您可以将 Java NIO 用于本机应用程序的网络层。 java.nio.channels.Selector 为您提供了 Java 等效项到C的select()。 java.nio.channels.Channel 类似于C 中的 fd。

此示例代码不是 Android 特定的,但应该可以工作(或者至少让您了解用法): http://www.exampledepot.com/egs/java.nio/NbClient.html

Perhaps you can use Java NIO for the network layer to your native app. The java.nio.channels.Selector gives you the Java equivalent to C's select(). And a java.nio.channels.Channel would be similar to an fd in C.

This example code isn't Android specific but should work nonetheless (or at least give you an idea of usage): http://www.exampledepot.com/egs/java.nio/NbClient.html

三生殊途 2024-10-18 01:07:32

至于 IPC:Looper - 或至少 NDK 实现 ALooper - 使用 POSIX pipe() 作为 IPC 的手段;您可以在 android_app_glue.c 中看到其中的一些内容,这是 NDK 的标准规定。作为该文件的参考,有问题的行是:

 int msgpipe[2];
    if (pipe(msgpipe)) {
        LOGE("could not create pipe: %s", strerror(errno));
        return NULL;
    }
    android_app->msgread = msgpipe[0];
    android_app->msgwrite = msgpipe[1];

关键行是

ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, &android_app->cmdPollSource);

其中第二个参数 (fd) 是一个文件描述符:

int ALooper_addFd   (   ALooper *   looper,
        int     fd,
        int     ident,
        int     events,
        ALooper_callbackFunc    callback,
        void *      data 
    )   

...如果他们将其用于 native_app_glue.c,用于游戏等,我想它是高效的。

As regards IPC: Looper - or at least the NDK implementation ALooper - uses a POSIX pipe() as a means of IPC; you can see some of this going on in android_app_glue.c, which is a standard provision of the NDK. For reference from that file, the lines in question are:

 int msgpipe[2];
    if (pipe(msgpipe)) {
        LOGE("could not create pipe: %s", strerror(errno));
        return NULL;
    }
    android_app->msgread = msgpipe[0];
    android_app->msgwrite = msgpipe[1];

and the key line is

ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, &android_app->cmdPollSource);

where the second argument (fd) a file descriptor:

int ALooper_addFd   (   ALooper *   looper,
        int     fd,
        int     ident,
        int     events,
        ALooper_callbackFunc    callback,
        void *      data 
    )   

...If they're using it for native_app_glue.c, used for games and so on, I'd imagine it's efficient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文