16

我最近听说过使用 emscripten 将 C++ 代码编译为 javascript,以及如果完成 asmjs 优化,它有可能真正快速地运行应用程序。

我已经阅读了几篇文章、教程,甚至还听过一些非常有趣的youtube 视频。我也成功运行了 hello world 示例。

但是,我不知道这种方法的全部功能,特别是如果一个全新的web 应用程序可以/应该作为一个整体用 C++ 编写,而不需要胶水代码。

更具体地说,我想写一些类似于以下 C++ 的东西(作为参考不工作的代码)。

#include <window>
class ApplicationLogic : public DOMListener{
private:
    int num;
public:
    ApplicationLogic():num(0);
    virtual void onClickEvent(DOMEventData event){
        num++;
    }
    virtual ~ApplicationLogic(){}
}

int main(){
    DOMElement but = Window.getElementById("foo");
    ApplicationLogic app();
    but.setOnclick(app);
}

我希望它可以明确这个想法,但目标是实现类似于:

  • 初始化模块的静态函数在窗口准备好时运行(与 jquery.ready() 的行为相同)。因此可以将侦听器添加到 DOM 元素中。

  • 一种直接从 C/C++ 与 DOM 交互的方式,因此#include <window>,基本上可以访问 DOM 和其他元素,如 JSON、Navigator 等。

我一直在思考 Lua,以及当 lua 脚本包含共享对象(动态链接库)时,它如何在该 .so 文件中搜索初始化函数,并且会注册从模块外部可用的函数,确切地说是如何返回asmjs 中创建的功能模块的作用。但我不知道如何直接用 C++ 模拟 jquery.ready。

正如你所看到的,我对 asmjs 知之甚少,但我没有找到我正在寻找的教程或类似内容,我已经阅读了对 stdlibc、stdlibc++ 和 SDL 的编译时包含的标准库的引用,但没有关于如何从 C++ 源代码操作 DOM。

4

2 回答 2

2

这是怎么回事。我知道这是一个老话题,但我在这里发帖以防其他人来这里寻找这个问题的答案(就像我一样)。

从技术上讲,是的,这是可能的——但是有大量你所谓的“胶水代码”,还有一些 JavaScript(这违背了 IMO 的目的)。例如:

#include <emscripten.h>
#include <string>

#define DIV 0
#define SPAN 1
#define INPUT 2
// etc. etc. etc. for every element you want to use

// Creates an element of the given type (see #defines above)
// and returns the element's ID
int RegisterElement(int type)
{
    return EM_ASM_INT({
        var i = 0;
        while (document.getElementById(i))
            i++;
        var t;
        if ($0 == 0) t = "div";
        else if ($0 == 1) t = "span";
        else if ($0 == 2) t = "input";
        else
            t = "span";
        var test = document.createElement(t);
        test.id = i;
        document.body.appendChild(test);
        return i;
    }, type);
}

// Calls document.getElementById(ID).innerHTML = text
void SetText(int ID, const char * text)
{
    char str[500];
    strcpy(str, "document.getElementById('");
    char id[1];
    sprintf(id, "%d", ID);
    strcat(str, id);
    strcat(str, "').innerHTML = '");
    strcat(str, text);
    strcat(str, "';");
    emscripten_run_script(str);
}

// And finally we get to our main entry point...
int main()
{
    RegisterElement(DIV);    // Creates an empty div, just as an example
    int test = RegisterElement(SPAN);    Creates an empty SPAN, test = its ID
    SetText(test, "Testing, 1-2-3");    Set the span's inner HTML
    return 0;    And we're done
}

我有同样的问题并想出了这个解决方案,它按预期编译和工作。但我们基本上是在构建一个 C/C++ API,只是为了做 JavaScript 已经“开箱即用”的事情。不要误会我的意思——从语言的角度来看,我每天都会使用 C++ 而不是 JavaScript——但我不禁认为这样的设置中涉及的开发时间和可能的性能问题是不值得的。如果我打算用 C++ 做一个 Web 应用程序,我肯定会使用 Cheerp(Duetto 的新名称)。

于 2017-03-16T08:17:05.810 回答
0

正如有人已经指出的那样,如果您从专门用于 Web 的新代码库开始,那么 duetto 可能是一个解决方案。但在我看来,duetto 有很多缺点,比如没有 C 分配器,如果你想使用 3rd 方库,这可能会变得非常困难。

如果您使用的是 emscripten,它为各种 DOM 事件提供了一个 API,它几乎完全符合您的要求。

emscripten_set_click_callback(const char *target, void *userData, int useCapture, int (*func)(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData));

希望这可以帮助

于 2014-05-09T12:39:43.170 回答