从标记为 extern C 的函数调用损坏的 class 实例方法

Calling mangled class instance methods from function marked extern C

我通常声明 class:

class Task {
    public:
        int test(int &c);
};


int Task::test(int &c) {
    c += 8;
    return c;
}

为了编译成 WASM,我试图实例化这个 class 并调用测试方法,如下所示:

extern "C" {
    Task t;

    int scratch() {
        int c = 123;
        t.test(c);
        return c;
    }
}

使用 extern "C" 指令来防止在 JS 模块上难以公开的名称重整。

然而,编译该程序出现错误undefined symbol: _ZN4Task4testERi (referenced by top-level compiled C/C++ code),表明“unmangled”int scratch() 方法无法调用“mangled”int Task::test(int &c) 方法。用 extern "C" 包装 class 定义和实现会产生相同的输出。

我怎样才能最好地从标记为 extern "C" 的函数的实例上调用 int Task::test(int &c)

Mangling 接近于允许低级链接器在 int foo(int)int foo(void) 之间产生差异而发明的 hack。您可以使用 extern "C" 明确禁止重整,但您声明符号具有该链接,因此它应该只用于普通函数,而不应用于 classes 或 class 成员。

惯用的方法是记住对非静态成员函数的调用带有一个隐藏的 this 指针。因此,您无需对 Task class 进行任何更改,而是声明一个普通函数作为中继:

extern "C" {
    int task_test(Task *obj, int *c) { // C language does not know about reference hence a pointer
        return obj->test(*c);
}