Closed Johnly1986 closed 3 years ago
My assumption is that most parts of OCC can be supported. That's especially true for everything that is "just" algorithmic - those parts should convert very easily into JavaScript + WASM. However, there are certain parts of OpenCascade (especially in the Visualization module), which rely on some kind of graphics output. I haven't used those interfaces - but I would assume those to be more difficult to expose to JavaScript (although Emscripten supports WebGL output, so this might actually work).
Generally speaking, there are certain limitations in Emscripten. However, generally my experience has been that most things just run out of the box, as Emscripten does a great job of "polyfilling" interfaces that do not exist on the web. A good example would be the file system API, which let you "simulate" a file system in JavaScript, so that C++ functions that rely on file loading and saving can work as usual.
There is one major annoyance at the moment though: JavaScript + the IDL syntax does not allow overloading of methods based on argument+return value types, Overloading in JavaScript only works when methods have different numbers of arguments. I.e. this would be an invalid IDL definition:
interface SomeClass {
void test(long value);
void test(double value);
};
However, it is possible to write the same kind of interface as valid C++ code. There are a couple of spots in the OpenCascade library, where this type of overloading is used. Therefore, these functions cannot be directly exposed to JavaScript without renaming them. The better long term solution would be to use Emscripten's Embind system instead of the IDL system. That's on my to-do list, but will take a while until implemented.
To expose additional interfaces, it should be enough to change the opencascade.idl
and potentially add missing include files here. Sometimes I use this file to define Handle-types, as that macro / template stuff doesn't work well with the IDL syntax. Then run python2 make.py && python2 make.py wasm
and it will generate the build files.
This is a very exciting project. There are only some small shortcomings, such as the wasm file is too large, the trouble of redefinition of functions, the referenced data structure, and so on;
Can you tell me how to distinguish between pointers and references in this system, and when to use "new".
Yeah, true... The WASM build is really quite large at 30MB (~30 seconds on a 3G network, ~3 seconds on 4G, ~2 seconds on my 100Mbit connection at home). However, if you're building your own version of the library, you can delete all unused interfaces and methods from the IDL file. This will allow Emscripten to perform dead-code-elimination, which reduces the size of the library. I have recently been working on a STEP/IGES/STL/OBJ file viewer (which does a couple of other things like volume calculation and shape healing for IGES files), where the WASM build came down to around 20MB. For super simple applications, I managed to get down to around ~13MB.
Can you tell me how to distinguish between pointers and references in this system
JavaScript passes all variables by value as shallow copies. When an OCCT method expects an argument to be passed as a pointer or reference, you indicate that with the [Ref]
flag in the IDL file. When passing references or pointers to variables of the JavaScript type number, string or boolean, those values will of course also be passed by value (another limitation). If a C++ function returns an object by value, this is indicated with the [Value]
flag in the IDL file (which has some caveats). More information is available in the Emscripten documentation.
and when to use "new"
You need to use new
in your JavaScript code, whenever you want to instantiate a new object (unlike C++ JavaScript doesn't differentiate between heap and stack - any object must be create with new
).
With regard to "new", why are all the return values marked with ref created with new. These objects have no new in the original C + + example.
I reported some errors when compiling the project with emscripten. Can you help me analyze it.
=====================================================
File " make.py ", line 285, in
build()
File " make.py ", line 243, in build
'-DBUILD MODULE ApplicationFramework=OFF'
File "D:\Program Files\Emscripten\emscripten\1.35.0\tools\ shared.py ", line 1141, in configure
process = Popen(args, stdout=None if EM BUILD VERBOSE LEVEL >= 2 else stdout, stderr=None if EM BUILD VERBOSE LEVEL >= 1 else stderr, env=env)
File "C:\Python27\lib\ subprocess.py ", line 394, in init
errread, errwrite)
File "C:\Python27\lib\ subprocess.py ", line 644, in execute child
startupinfo)
Windowserror: [error 193]% 1 is not a valid Win32
With regard to "new", why are all the return values marked with ref created with new. These objects have no new in the original C + + example.
I reported some errors when compiling the project with emscripten. Can you help me analyze it.
=====================================================
File " make.py ", line 285, in
build()
File " make.py ", line 243, in build
'-DBUILD MODULE ApplicationFramework=OFF'
File "D:\Program Files\Emscripten\emscripten\1.35.0\tools\ shared.py ", line 1141, in configure
process = Popen(args, stdout=None if EM BUILD VERBOSE LEVEL >= 2 else stdout, stderr=None if EM BUILD VERBOSE LEVEL >= 1 else stderr, env=env)
File "C:\Python27\lib\ subprocess.py ", line 394, in init
errread, errwrite)
File "C:\Python27\lib\ subprocess.py ", line 644, in execute child
startupinfo)
Windowserror: [error 193]% 1 is not a valid Win32
process = Popen(args, shell=True, stdout=None if EM_BUILD_VERBOSE_LEVEL >= 2 else stdout, stderr=None if EM_BUILD_VERBOSE_LEVEL >= 1 else stderr, env=env) This may be an emscripten bug. It cannot be compiled normally without "shell = true" in win10 operating system
When I use the "python make.py wasm" command, an exception occurred again. The exception content is
====================================================================== Traceback (most recent call last):
File "D:\Program Files\Emscripten\emscripten\1.35.0\emcc", line 960, in
assert not shared.Settings.ALLOW MEMORY GROWTH, 'memory growth is not supported with WASM=1'
AssertionError: memory growth is not supported with WASM=1
Traceback (most recent call last):
File " make.py ", line 287, in
build()
File " make.py ", line 266, in build
emscripten.Building.emcc ('-DNOTHING WAKA WAKA', emcc args + ['glue.o'] + opencascade libs + myincludes[:len(myincludes)-2] + ['--js-transform', 'python %s' % os.path.join ('..', ' bundle.py ')], temp)
File "D:\Program Files\Emscripten\emscripten\1.35.0\tools\ shared.py ", line 1550, in emcc
assert os.path.exists (output filename), 'emcc could not create output file: ' + output filename
AssertionError: emcc could not create output file: .\js\ opencascade.wasm.js
========================================================================
I think these problems may be due to different operating systems or versions of emscripten. In order for more people to use it, maybe you need to make this information public.
process = Popen(args, shell=True, stdout=None if EM_BUILD_VERBOSE_LEVEL >= 2 else stdout, stderr=None if EM_BUILD_VERBOSE_LEVEL >= 1 else stderr, env=env) This may be an emscripten bug. It cannot be compiled normally without "shell = true" in win10 operating system
Awesome, thanks for sharing that. I will add that into the script then. Glad that you're making progress.
I think these problems may be due to different operating systems or versions of emscripten. In order for more people to use it, maybe you need to make this information public.
I'm using Manjaro Linux to build this. I haven't tried any other operating systems. However, I think I will create a simple Dockerfile
, so that you can more easily build the application under any host operating system by creating a Docker container with a correctly configured build operating system.
process = Popen(args, shell=True, stdout=None if EM_BUILD_VERBOSE_LEVEL >= 2 else stdout, stderr=None if EM_BUILD_VERBOSE_LEVEL >= 1 else stderr, env=env) This may be an emscripten bug. It cannot be compiled normally without "shell = true" in win10 operating system
Awesome, thanks for sharing that. I will add that into the script then. Glad that you're making progress.
I think these problems may be due to different operating systems or versions of emscripten. In order for more people to use it, maybe you need to make this information public.
I'm using Manjaro Linux to build this. I haven't tried any other operating systems. However, I think I will create a simple
Dockerfile
, so that you can more easily build the application under any host operating system by creating a Docker container with a correctly configured build operating system.
Can you share a docker for me? Now my head will split. Although the compiler passes, the file does not seem to load normally.
Hi, I just made a few commits to the master branch which make this project work with Docker. It would be great, if you could try this and let me know if this works on your end.
Before starting, you probably want to install Docker for windows.
You probably also want to delete the opencascade.js/build
directory, if it exists and use git pull
to make sure you have all the latest changes on your disk.
Then you have to open up a command prompt in the directory of opencascade.js
. Under linux, I execute the build as follows
docker build -t opencascade .
docker run -it -v "$(pwd)/build":"/opencascade/build" -v "$(pwd)/dist":"/opencascade/dist" opencascade
You have to run both commands, whenever you make changes to any file and want to build the library again. The first command will build a container, which is based on an Ubuntu linux and configures it for running the build. The second command runs the build. It creates two directories, which will be shared with your host system: build
and dist
. build
contains temporary build files (so that you don't have to recompile the entire library, each time you make a small change). dist
contains the final WASM + JS builds.
Under linux, I use $(pwd)
to tell docker to use the current directory in the path for the shared folders (print working directory). I guess under windows, you should probably use something like the following:
docker build -t opencascade .
docker run -it -v "%cd%/build":"/opencascade/build" -v "%cd%/dist":"/opencascade/dist" opencascade
Not sure if this is the correct syntax though. Would be great if you could let me know if this works for you!
PS: When you run those commands for the first time, it will probably take very long to run (on my machine, its around an hour). For successive builds, it will run much faster.
There are now instructions on how to build with Docker in the readme.
Can all interfaces of OCC be supported. If I change it opencascade.idl , do you need to make other changes?