从标记为 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);
}
我通常声明 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);
}