WebGl C++ Plugin with static lib

I am working on a Webgl plugin and want to add a library(.lib/ dll/ framework/ bundle) inside it.

You cannot run code compiled for other platforms (as the lib/ dll/ framework/ bundle would suggest) to webgl. What are you trying to achieve?

Thanks for your reply. I have c++ code of it but number of files is huge. For all other platforms I have created respected libraries but want to know how to create a lib for webgl and use it.

You can use the emscripten compiler toolchain to compile your files into a single .bc (llvm bitcode) file. The bc file can be included in unity as a plugin, similar to lib/dll/framework/bundle files on other platforms.

Thank you for showing the way. I will be trying it.

I"m not sure if this blog post will be helpful here, because it doesn’t seem to cover that particular use-case:

https://blogs.unity3d.com/2017/01/19/low-level-plugins-in-unity-webgl/

So here is a question, if I compile a C/C++ library to llvm bitcode, I still have to write the same p/invoke C# code to interface to it, correct? Is the only difference from using a native .dll/.so is that I would just reference .bc file?

Yes, if you compile C/C++ code to llvm bitcode, you still need to write the C# bindings for it like you normally would for other plugins.

What does the optimizer do in the case of AOT compiling? Do the C# bindings have any performance impact due to p/invoke or do they get optimized away?

I’ve built a simple static lib from very simple .c source file into a .bc file but I can’t never call the function from c#.
My .c file is:

#include <stdio.h>

int AddNumbers (int x, int y)
{
    return x + y;
}

and then on c#

    [DllImport("__Internal")]
    private static extern int AddNumbers(int x, int y);

To compile the .c file I’ve created a MakeFile using CMake and compiled it with Emscripten

./emmake make

It generates a .a lib file that I’ve renamed to .bc and moved into Unity Assets and market as a WebGL plugin.
When i call the AddNumber method I always get this error:

An error occurred running the Unity content on this page. See your browser's JavaScript console for more info. The error was:
abort(-1) at jsStackTrace (WebGLPlugin.js:1:19708)
stackTrace (WebGLPlugin.js:1:19882)
abort (WebGLPlugin.js:3:32695)
_AddNumbers (WebGLPlugin.js:1:186759)
Pwo (WebGLPlugin.asm.js:10:844115)
N_l (WebGLPlugin.asm.js:4:87306)

If I just drop the .c file inside Unity Assets it runs without a problem.
The reason I want to create the .bc file is because I want to compile a much larger code base.

Thanks

I don’t think you do it that way. The .lib file is not the right bitcode format.

Try building the .c file with emscripten with the -emit-llvm flag set to generate the IL code.

I found an article on stack overflow that might be useful: How do I generate LLVM bitcode for use by emscripten? - Stack Overflow

1 Like

Thanks for the guidance.
I’ve added ā€˜-emit-llvm’ to CFLAGS and i still can’t get it to work. I must be missing something obvious here.

Did you try using the toolchain that is supplied by Unity? Also, apparently not all llvm bitcode is equal in the emscripten world. I’m still doing some research, so hopefully I’ll find something useful.

I could compile it now using clang directly.

clang -emit-llvm -o MyPlugin.bc -c MyPlugin.c

Then I just need to drop the MyPlugin.bc inside Unity and it will work.
I was always under the impression I would need to compile it using emscripten.

Thanks for the help :slight_smile:

You would still need to write a C# wrapper, and I believe you have to use the usual [DllImport(…)] stuff. I’m not sure if you would be able to get away with DllImport(ā€œ__Internalā€) or not, you’ll have to check the Unity docs.

Yes I still need the c# wrapper just with [DllImport(ā€œ__Internalā€)].
Although I can compile it using clang directly I’m having a hard time making that possible with CMAKE.
Added set (CMAKE_C_FLAGS ā€œ-emit-llvm -cā€) to CMakeLists.txt but the resulting lib doesn’t work.

Ok, so to make it work with CMake I had to set the compiler and linker executables to use the ones from Emscripten.
I now can run that simple .c code.
I can also compile my c/c++ codebase into a llvm bitcode file (.bc) but when I build it with Unity WebGL I get an error upon running.

abort(-1) at jsStackTrace (WebGLPlugin.js:1:19708)
stackTrace (WebGLPlugin.js:1:19882)
abort (WebGLPlugin.js:3:32695)
_llvm_objectsize_i64_p0i8 (WebGLPlugin.js:1:299381)
t3e (WebGLPlugin.asm.js:11:461661)
a4e (WebGLPlugin.asm.js:11:498065)
...
1 Like

Is your C++ codebase large? Have you tried just a simple C++ module like hello world?

I’ve tried with simple files and it works fine. My codebase is a bit large :frowning:

In my last attempt to compile a C/C++ library to a bitcode (.bc) static library I got an error that this is no longer supported on Emscripten upstream. I switched back to Emscripten fastcomp for now, but this is not recommended anymore:

emcc: warning: the fastcomp compiler is deprecated.  Please switch to the upstream llvm backend as soon as possible and open issues if you have trouble doing so [-Wfastcomp]

The newer Emscripten (upstream/llvm) creates ā€œ.aā€ library files. Can those be used as well and with which versions of Unity?

Is there a table showing which Unity version uses what exact Emscripten version, so we can match them?

Thanks!

P.S.: sorry for digging out this old post, but it’s the top search result.

1 Like

We’ve only started looking at this again recently. It’s now 2022, so if we discover anything I’ll post about it here.