Reputation: 67
I'm trying to compile a C++ library (pure code) to a .wasm file for Wasmer so I can run them universally in the server side regardless of what OS it's on. However I find rare documentation which can help me deal with C++ class.
For details, all helpful functions I wanted are in a C++ class named Timer, like Timer.reset()
. But it seems that Wasmer can only use exported functions
on it's documentation. So it is possible to use exported c++ classes like instance.exports.Timer.reset()
in Wasmer?
The main confusion is also about how to wrap this Timer
class in .wasm file. I checked emscripten doc which shows this. But the documentation compile them to .js
files instead of .wasm
.
Questions above combined, I find it hard to get clear procedures to use c++ classes in Wasmer for other programming languages.
I hope I've made a clear problem explanation for anyone willing to give some hints. Bests.
Upvotes: 4
Views: 1325
Reputation: 4936
or you can do "the old way" wrapping it in c calls:
#include <emscripten.h>
#include <emscripten/bind.h>
class Foo {
public:
int i;
};
class MyClass {
public:
int x;
Foo foo;
};
typedef void *MyClassHandle, *FooHandle;
MyClassHandle createMyClass() {
return static_cast<MyClassHandle>(new MyClass());
}
void destroyMyClass(MyClassHandle handle) {
delete static_cast<MyClass *>(handle);
}
FooHandle getFoo(MyClassHandle handle) {
MyClass *This = static_cast<MyClass *>(handle);
return static_cast<FooHandle>(&This->foo);
}
int getFooInt(FooHandle foo) {
return static_cast<Foo *>(foo)->i;
}
EMSCRIPTEN_BINDINGS(test) {
function("createMyClass", &createMyClass, emscripten::allow_raw_pointers());
function("destroyMyClass", &destroyMyClass, emscripten::allow_raw_pointers());
function("getFoo", &getFoo, emscripten::allow_raw_pointers());
function("getFooInt", &getFooInt, emscripten::allow_raw_pointers());
}
Upvotes: 2
Reputation: 166379
Check the following pull request: Enable accessing fields that are classes without copying.
Using it, you can expose C++ classes as properties using the following example (from the PR):
class Foo {
public:
int i;
};
class MyClass {
public:
int x;
Foo foo;
int getY() const { return y; }
void setY(int y_) { y = y_; }
private:
int y;
};
EMSCRIPTEN_BINDINGS(test) {
class_<MyClass>("MyClass")
.constructor()
.property("x", &MyClass::x) // Expose a field directly.
.property("y", &MyClass::getY, &MyClass::setY) // Expose through a getter and setter.
.property("readOnlyY", &MyClass::getY) // Expose a read only property.
.property("foo", &MyClass::foo); // Expose a class field.
class_<Foo>("Foo")
.constructor()
.property("i", &Foo::i);
}
Then in Javascript, you can use the following code to use them:
var myClass = new Module.MyClass();
myClass.x = 10;
myClass.x; // 10
myClass.y = 20;
myClass.y; // 20
myClass.readOnlyY; // 20
// Assign directly to the inner class.
myClass.foo.i = 30;
myClass.foo.i; // 30
// Or use Foo object to assign to foo.
var foo = new Module.Foo();
foo.i = 40;
// Note: this will copy values from the foo but the objects will remain separate.
myClass.foo = foo;
myClass.foo.i; // 40
myClass.delete();
foo.delete();
Upvotes: 2