How to run webidl_binder.py?

46 views
Skip to first unread message

キャロウ マーク

unread,
Apr 21, 2020, 7:55:34 PM4/21/20
to emscripten-discuss
Yes this seems like a really simple and stupid question, bear with me.

The documentation https://emscripten.org/docs/porting/connecting_cpp_and_javascript/WebIDL-Binder.html just has a link to the source for the binder in the Emscripten GitHub repo. It says nothing about how you actually use it. Typing `webidl_binder.py` even prefixed with `python` gets a not found error. A `find` in my emsdk root reveals the tool is in upstream/emscripten/tools. The emsdk installer did not add the directory to $PATH from which it seems you aren’t meant to run it directly. However I can’t find any options in emcc to run the binder and it proclaims ignorance of the `.idl` extension if I just pass the file to it.

So, am I supposed to add  `upstream/emscripten/tools` to my $PATH or is there another way I’m supposed to run it. If the former, why doesn’t emsdk add this directory to $PATH?

Regards

    -Mark

signature.asc

キャロウ マーク

unread,
Apr 22, 2020, 1:08:38 AM4/22/20
to emscripten-discuss
I discovered that I copied the emsdk $PATH additions into my .bash_profile - because I want them visible to something called osx-env-sync.sh. It is possible that a more recent `emsdk construct_env` may be adding the tools directory.

However webidl_binder.py does not have a #! line so can’t be run as a shell plus it does not have execute permission (I’m using a clone of the Emscripten repo) making it very difficult to run from the command line. Surely there must be a simpler way than `python $EMSDK/upstream/emscripten/tools/webidl_binder.py`. Yes I know I can make aliases and scripts, etc. etc. but why should I have to. I don’t have to in order to run `emcc`.

Regards

    -Mark

signature.asc

キャロウ マーク

unread,
Apr 22, 2020, 4:55:56 PM4/22/20
to emscripten-discuss
I am running the binder the long-winded way. I am finding that it is leaving little turds behind, a file called “parser.out” and another called “WebIDLGrammar.pkl”.

So I repeat my question. What is the proper way to run the binder? Will that still leave turds behind? Why the silence? Isn’t anyone else using this or do you all think my question so dumb it doesn’t deserve an answer?

Regards

    -Mark

signature.asc

キャロウ マーク

unread,
Apr 22, 2020, 7:27:59 PM4/22/20
to emscripten-discuss
The binder is emitting the following code into the .cpp file:

void array_bounds_check(const int array_size, const int array_idx) {
  if (array_idx < 0 || array_idx >= array_size) {
    EM_ASM({
      throw 'Array index ' + $0 + ' out of bounds: [0,' + $1 + ')';
    }, array_idx, array_size);
  }
}

emcc barfs on " '$' in identifier [-Wdollar-in-identifier-extension]”. WebIDL-Binder.html says nothing about either EM_ASM or ‘array_bounds_check’. And I don’t see any flag to emcc relevant to enabling ASM_JS. How do I fix this?

I feel like I’m blazing a new trail here yet there are examples pointed at by WebIDL-Binder.html. However I was unable to find the build scripts, .yml files make fles or whatever, for either of the examples.

Regards

    -Mark

signature.asc

Alon Zakai

unread,
Apr 23, 2020, 2:10:11 PM4/23/20
to emscripte...@googlegroups.com
It might be good to look at how it's used in the test suite,


Looks like it just does python and then the path to the binder. I agree that emsdk integration could be better, seems like right now you need to give it the full path into the subdirectory of the emsdk where it exists.

I also agree those temp files shouldn't be emitted. I'm not sure offhand why that happens, it could be due to the IDL parser library we use, which we didn't write ourselves. Worth filing an issue, hopefully someone can look into that.



--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/EDD7D00E-4DC6-4025-8D55-11A914BE7F68%40callow.im.

キャロウ マーク

unread,
Apr 23, 2020, 5:54:56 PM4/23/20
to emscripte...@googlegroups.com
signature.asc

キャロウ マーク

unread,
Apr 23, 2020, 6:10:30 PM4/23/20
to emscripte...@googlegroups.com
[ Sorry about the previous empty message. Finger slip.]

Hi Alon,

On Apr 23, 2020, at 11:09, Alon Zakai <alon...@gmail.com> wrote:


Thanks. I tried to find this by working back from the test link given in the webidl_binder documentation but failed.


Looks like it just does python and then the path to the binder. I agree that emsdk integration could be better, seems like right now you need to give it the full path into the subdirectory of the emsdk where it exists.



I also agree those temp files shouldn't be emitted. I'm not sure offhand why that happens, it could be due to the IDL parser library we use, which we didn't write ourselves. Worth filing an issue, hopefully someone can look into that.


I also filed https://github.com/emscripten-core/emscripten/issues/10987 about the very, very low signal to noise ratio in webidl_binder’s output when reporting a syntax error.

...

The binder is emitting the following code into the .cpp file:

void array_bounds_check(const int array_size, const int array_idx) {
  if (array_idx < 0 || array_idx >= array_size) {
    EM_ASM({
      throw 'Array index ' + $0 + ' out of bounds: [0,' + $1 + ')';
    }, array_idx, array_size);
  }
}

emcc barfs on " '$' in identifier [-Wdollar-in-identifier-extension]”. WebIDL-Binder.html says nothing about either EM_ASM or ‘array_bounds_check’. And I don’t see any flag to emcc relevant to enabling ASM_JS. How do I fix this?


How can I stop this? the test runner doesn’t seem to set any special emcc options relevant to this.

I could turn off warnings as errors so I’d just get noise but I do not want to do that. At the moment this is blocking me from further progress.

Regards

    -Mark




signature.asc

Alon Zakai

unread,
Apr 23, 2020, 6:37:09 PM4/23/20
to emscripte...@googlegroups.com
I think we can fix that by avoiding an EM_ASM. Currently EM_ASMs need $'s in their params. Instead, we could rewrite that to use an EM_JS which avoids that.


But there are others which are less trivial. Maybe if you have time you can take a look, a PR would be very welcome. Or, meanwhile you can disable that warning on that file maybe.
 
I could turn off warnings as errors so I’d just get noise but I do not want to do that. At the moment this is blocking me from further progress.

Regards

    -Mark




--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.

キャロウ マーク

unread,
Apr 25, 2020, 4:18:26 PM4/25/20
to emscripten-discuss
I need an ArrayBuffer, actually a Uint8Array, passed from JS to my C++ class. With embind my c++ class has

texture(const emscripten::val& data) {
std::vector<uint8_t> bytes{};
bytes.resize(data["byteLength"].as<size_t>());
emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
emscripten::val memoryView = data["constructor"].new_(memory, reinterpret_cast<uintptr_t>(bytes.data()), data["length"].as<uint32_t>());
memoryView.call<void>("set", data);
….
}

How to I do the same using webidl_binder?

In another method of this class, I need to return multiple items including something retrieved from module_property. With embind I use an emscripten::val as follows:

val ret = val::object();
// Find the WebGLTexture for texture.
val texture = val::module_property("GL")["textures"][texname];
ret.set("texture", texture);
ret.set("target", target);
ret.set("error", error);
return std::move(ret);

I am trying to figure out how to do the equivalent with webidl_binder. I created a

struct UploadResult {
val texture;
GLenum target;
GLenum error;
};

in my c++ class and a matching interface in the idl and this is what the method is declared to return. My current attempt is

UploadResult ur;
val texture = val::module_property("GL")["textures"][texname];
ur.texture = std::move(texture);
ur.target = target;
ur.error = error;
return std::move(ur);

I am getting errors about “implicitly-deleted default constructor” for both ur and val. The use of `val` here raises another question. How do I look something up in module_property?

The webidl_binder documentation fails to describe any interesting uses, limiting itself to only the most basic types and operations.

Regards

-Mark


signature.asc

キャロウ マーク

unread,
Apr 25, 2020, 8:15:24 PM4/25/20
to emscripte...@googlegroups.com


On Apr 25, 2020, at 13:18, キャロウ マーク <git...@callow.im> wrote:

I am trying to figure out how to do the equivalent with webidl_binder. I created a

   struct UploadResult {
       val texture;
       GLenum target;
       GLenum error;
   };

in my c++ class and a matching interface in the idl and this is what the method is declared to return. My current attempt is

           UploadResult ur;
           val texture = val::module_property("GL")["textures"][texname];
           ur.texture = std::move(texture);
           ur.target = target;
           ur.error = error;
           return std::move(ur);

I am getting errors about “implicitly-deleted default constructor” for both ur and val. The use of  `val` here raises another question. How do I look something up in module_property?


I almost have it working with

            UploadResult ur(
                val::module_property("GL")["textures"][texname],
                target = target,
                error = error);
            return std::move(ur);

where UploadResult is 

    struct UploadResult {
        val texture;
        GLenum target;
        GLenum error;

        UploadResult() { };
        UploadResult(val texture, GLenum target, GLenum error)
             : texture(texture), target(target), error(error) { }
    };

The relevant IDL is

interface WebGLObject {
};

interface WebGLTexture : WebGLObject {
};

interface UploadResult {
    [Value] readonly attribute WebGLTexture texture;
    readonly attribute GLenum target;
    readonly attribute GLenum error;
};

interface texture {
    void texture(Uint8Array fileData);
    [Value] UploadResult glUpload();
    …
}


However, there is still 1 problem:

  1. The stub in the generated .cpp file is attempting to put the UploadResult into a temporary stack variable which raises the “implicitly deleted default constructor error”. If I make a no args constructor then the message changes to  "call to deleted constructor”.


signature.asc

キャロウ マーク

unread,
Apr 26, 2020, 3:34:42 PM4/26/20
to emscripte...@googlegroups.com
On Apr 25, 2020, at 13:18, キャロウ マーク <git...@callow.im> wrote:

I need an ArrayBuffer, actually a Uint8Array, passed from JS to my C++ class. With embind my c++ class has

    texture(const emscripten::val& data) {
           std::vector<uint8_t> bytes{};
           bytes.resize(data["byteLength"].as<size_t>());
           emscripten::val memory = emscripten::val::module_property("HEAP8")["buffer"];
           emscripten::val memoryView = data["constructor"].new_(memory, reinterpret_cast<uintptr_t>(bytes.data()), data["length"].as<uint32_t>());
           memoryView.call<void>("set", data);
           ….
    }

How to I do the same using webidl_binder?

I managed to get something compiled and linked using the above code. However when it is called, from JS `data` is “undefined”.

On this line

ktexture = new Texture(ktxdata);

the debugger shows ktxdata to be as expected. But inside the JS part of the constructor: 

// Texture
/** @suppress {undefinedVars, duplicate} */function Texture(fileData) {
  if (fileData && typeof fileData === 'object') fileData = fileData.ptr;
  this.ptr = _emscripten_bind_Texture_Texture_1(fileData);
  getCache(Texture)[this.ptr] = this;
};;

the debugger shows fileData is undefined.

So apparently using emscripten::val is not the right way to pass a typed array to my C++. Unfortunately


does not say anything about this and the 2 real examples it points to do not use ArrayBuffers so they are no help.

Somebody please tell me how to pass in a typed array. I think I’m barking up the wrong tree trying to use emscripten::val with webidl_binder. Am I correct? How to I deal with objects from the Javascript side?

I wouldn’t be asking these questions if the documentation was adequate.

Regards

    -Mark
signature.asc
Reply all
Reply to author
Forward
0 new messages