-
Notifications
You must be signed in to change notification settings - Fork 121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Call a nbind::cbFunction with nbind::Buffer? #91
Comments
I am interested in this functionality too, to provide memory view into some std::vector to the javascript side. From browsing the sources, it looks like we can not use nbind/include/nbind/v8/Buffer.h Line 52 in d5b051a
BindingType instantiation for this, I'll let you know if it works =)
|
@Luthaf, thanks for looking into this! I think the reason it wasn't implemented before is complexities in the Emscripten target. JavaScript can receive a view of the C++ memory, but would have to explicitly release the reference because in browsers, the C++ code cannot know when the JavaScript object gets garbage collected. Then it's easy to leak memory in the C++ heap, which is already restricted to a constant size. Another option is to pass the buffer as a copy, but that negates many of the benefits. Can you think of a solution portable also into Emscripten? Otherwise, this could still be released as a native-only feature. |
I am not sure I understand the issue here. Do C++ destructors still run with Emscripten? Then the problem is that we don't know when to run destructors because the JS side could still be holding a reference to the buffer data? My use case looks like this: class Container {
private:
// buffer is something like a std::vector,
// except I can't access the actual std::vector directly
some_type buffer;
public:
size_t length() {return data.length();}
double* data() {return &buffer[0];}
} I would like to provide read and write access to the data to the JS side, but I don't want the JS side to free the memory at any point. The C++ object is the owner of the memory. This is fundamentally unsafe, as the vector can be resized and then the pointer becomes invalid. But this is OK for my use case. I've got something working with the following code, but I only implemented the node.js part for now. |
Exactly, in Emscripten we can't know what references JS is holding. It's like security boxing is reversed compared to Node.js native code: C++ is limited to accessing a single typed array and has no knowledge of JS engine internals. Meanwhile JS has direct access to the entire C++ heap. The current Returning buffers would be more performant in Emscripten, because they can be views into the C++ heap. Meanwhile JS-allocated arrays are currently copied, because the Asm.js engine has no memory mapping support for directly accessing any JS object other than its own initial heap. |
Ok, so what I need is different from |
It seems like a useful addition to nbind. I guess from C++ you'd return a struct by value, containing Such an wrapper object already exists here in External.h. It seems it could be re-used, if the template argument is changed from The I guess you could use |
For those looking for a working example of this, I have a Node binding working here passing a buffer via a callback: On the JS side I had to use a slice to avoid memory issues: https://github.com/openzim/node-libzim/blob/e790bfc55352a027f1e4d7e8acce9bfaf369c461/src/ZimReader.ts#L39 This is currently a bit of a hack and definitely not efficient, but it's working well enough for demos 😄 |
Is it possible to create an nbind::Buffer object inside a wrapped function and send that object to Javascript via a callback? I created the following example but all I see on the Javascript side a null.
Corresponding JavaScript code (buftest.js):
Outputs:
Attempting to
console.log(buf.length)
results in aTypeError: Cannot read property 'length' of null
The text was updated successfully, but these errors were encountered: