emscripten-core / emscripten-core/emscripten
Overloads, bound types, and native types confusion
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
**Version of emscripten/emsdk:**
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.30 (cfe2bdfe2692457cb5f5770672f6e5ccb3ffc2f2)
clang version 16.0.0 (https://github.com/llvm/llvm-project 800f0f1546b2352ba42a4777149afb13cb874fcd)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /emsdk/upstream/bin
**Issue**
I am trying to take advantage of overloading a series of methods that have the same return type (void) but different arguments.
Historically we've avoided this because when we first started using emscripten, it was not supported. Revisiting it now, it seems it is almost working, but I have a case where it is not.
[Our project](https://github.com/mcneel/rhino3dm) links our [OpenNURBS](https://github.com/mcneel/opennurbs/tree/8.x) library with some c++ bindings, and generates wasm. This has been working well, in general. There are several situations where it would be nice to use overloaded functions.
Here is an example where I am trying to use overloaded functions: https://github.com/mcneel/rhino3dm/blob/dev/src/bindings/bnd_pointcloud.h#L51
The methods I would like to overload (before I was calling them Add1, Add2, etc):
```cpp
void Add(ON_3dPoint point);
void Add(ON_3dPoint point, double value);
void Add(ON_3dPoint point, ON_3dVector normal);
void Add(ON_3dPoint point, BND_Color color);
void Add(ON_3dPoint point, ON_3dVector normal, BND_Color color);
```
As you see, there are arguments with built in types (`double`), native types (`ON_3dPoint`, `ON_3dVector`), and bound types (`BND_Color`).
The [methods are bound](https://github.com/mcneel/rhino3dm/blob/dev/src/bindings/bnd_pointcloud.cpp#L737C3-L778C6):
```cpp
class_>("PointCloud")
.constructor<>()
// ... //
.function("add", select_overload(&BND_PointCloud::Add))
.function("add", select_overload(&BND_PointCloud::Add) )
.function("add", select_overload(&BND_PointCloud::Add)
.function("add", select_overload(&BND_PointCloud::Add) )
.function("add", select_overload(&BND_PointCloud::Add) )
// ... //
;
```
The issue is specifically between
- `.function("add", select_overload(&BND_PointCloud::Add) )`
- `.function("add", select_overload(&BND_PointCloud::Add) `
- `.function("add", select_overload(&BND_PointCloud::Add) )`
When trying to use the add method that takes `ON_3dPoint, ON_3dVector` OR `ON_3dPoint, double`, the code goes to the method that uses `ON_3dPoint, BND_Color`. These all have 2 args, where the second arg is what is changing.
When trying to debug, I notice that the overload table only has 3 methods, when in actuality there are 5 (although the array las a length of 4):
So it seems that the method taking `ON_3dPoint, ON_3dVector` and `ON_3dPoint, double` is somehow skipped and thus we run the wrong method and get an exception because of the wrong type.
The specific error:
```js
TypeError: Cannot convert "undefined" to int
at checkAssertions (rhino3dm.module.js:6644:17)
at Object.toWireType (rhino3dm.module.js:6658:11)
at __emval_as (rhino3dm.module.js:7110:38)
at int emscripten::val::as() int emscripten::val::as() const (val.h:544)
at Binding_to_ON_Color(emscripten::val Binding_to_ON_Color(emscripten::val const&) (bnd_color.cpp:49)
at BND_PointCloud::Add(ON_3dPoint, BND_PointCloud::Add(ON_3dPoint, emscripten::val) (bnd_pointcloud.cpp:248)
at emscripten::internal::MethodInvoker::invoke(void (BND_PointCloud::* const&)(ON_3dPoint, emscripten::val), BND_PointCloud*, ON_3dPoint*, emscripten::internal::MethodInvoker::invoke(void (BND_PointCloud::* const&)(ON_3dPoint, emscripten::val), BND_PointCloud*, ON_3dPoint*, emscripten::_EM_VAL*) (bind.h:600)
at PointCloud.PointCloud$add (eval at new_ (rhino3dm.module.js:6032:27), :11:1)
at proto. [as add] (rhino3dm.module.js:5529:68)
at script.js:12:8
```
The reason it is `Cannot convert "undefined" to int` I suppose is because the type it is expecting is a color, and it is trying to access a color channel which is int.
What could I do to further debug this issue, or to provide any information that might help others understand what is going on? I have seem older issues that deal with overloading, and their progress sounded promising, but it seems that there are still issues with the overloading code. Any suggestions would be greatly appreciated!
Contributor guide
Assessment
This issue has not been assessed yet.