Skip to content
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

gRPC support for HoloLens2 with Unity #23488

Closed
tom-r-o opened this issue Jul 15, 2020 · 26 comments
Closed

gRPC support for HoloLens2 with Unity #23488

tom-r-o opened this issue Jul 15, 2020 · 26 comments

Comments

@tom-r-o
Copy link

tom-r-o commented Jul 15, 2020

Is your feature request related to a problem? Please describe.

I'd like to use gRPC in Unity in HoloLens2. HoloLens2 runs windows on an ARM64 CPU, and requires a dedicated grpc_csharp_ext.dll.

Describe the solution you'd like

I'd like:

  1. grpc_csharp_ext.dll for windows ARM64 to be delivered as part of the gRPC package.

  2. A working build for Unity and HoloLens2 (as part of Official gRPC Releases).

Describe alternatives you've considered

I've managed to get grpc_csharp_ext.dll for windows arm64 with vcpkg by running:

vcpkg install grpc:arm64-windows

Following these steps helps compile the Unity application, but for some reason I'm getting this error message:

System.DllNotFoundException: Unable to load DLL 'grpc_csharp_ext.dll': The specified module could not be found.

Additional context

Unity uses C#, but for uwp windows they use an IL2CPP compiler. I.e. the C# code is converted to C++ (IIUC).
I've seen some related threads, but not one that discusses HoloLens2+Unity specifically, so I hope this isn't redundant with other threads.

@veronicagarciavazquez
Copy link

veronicagarciavazquez commented Jul 17, 2020

I have the same goal: to run grpc on HoloLens 2.

I have compiled grpc for ARM64 with vcpkg as you said. In my Unity project (Unity 2019.3.15f1) I use the package MSBuildForUnity to install the packages Google.Protobuf and Grpc.Core. I have created a Plugins folder in Assets where I copy the grpc_csharp_ext.dll for x64 and ARM64. I set up for each dll (Inspector) its corresponding platform. The dll for x64 is from UnityApp\Assets\Dependencies\net46\grpc_csharp_ext.x64.dll (I renamed the file as grpc_csharp_ext.dll, not sure yet why Unity does not find this dll automatically when you press Play button) and the dll for ARM64 is from \vcpkg\buildtrees\grpc\arm64-windows-dbg\grpc_csharp_ext.dll. After I checked that everything works in Unity editor, I built the Visual Studio project in Unity. In Visual Studio 2019, when I build the project for ARM64 I have a lot of linking errors like:

Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol grpcsharp_version_string referenced in function DllImportsFromStaticLib_grpcsharp_version_string_mBA017FAEEF230F896AFE112589C7758B2A1E020A Il2CppOutputProject C:\HoloLens2_projects\HoloLens2_NavEVAR\App\Il2CppOutputProject\9198B2E46770E7F49EAE971D0DC4BADF.obj 1

Could the errors come from having different grpc versions? The version of grpc in cvpkg is 1.29.1 while the version downloaded by MSBuildForUnity is 2.30.0. I have tried to download the version 1.29.1 but there isn´t this version of the NuGet package. The closest version of grpc that I can get is 2.23 (not 1.29.1). I have also tried with this version but the same errors in Visual Studio. Any idea of how to solve these linking errors? Thanks!

@tom-r-o
Copy link
Author

tom-r-o commented Jul 19, 2020

To get the project to compile I've followed the steps here: #20344 (comment)

I used the exact same version as in the post, which is 1.25.
So I also have some version mismatch, having the grpc_csharp_ext.dll at 1.29.1 and the rest of the dlls in version 1.25. Since the issue is that the dll is not found I don't think that the version mismatch is the issue (I also hope that the C++ 1.29.1 dll is backwards compatible with calls from a C# 1.25 dll). Also note, it may be possible to get an older grpc_csharp_ext.dll by reverting the vcpkg repo to an older version. I haven't figured out how to get exactly 1.25, and haven't looked into it since the error message I'm getting doesn't seem related.

To isolate the problem I manually created a C++ dll and a C# project that invokes a simple function from that dll. This also yields a "dll not found" exception on the HoloLens2 (while it works fine in the Unity IDE). So at the moment I'm looking into how to get DllImport to work on HoloLens2.

If you follow these steps please let me know if and how you've managed to get this working on the HoloLens2, and if so - how.

Note:
There are two similar possible commands in vcpkg that can yield a dll that may match the HoloLens2:

vcpkg install grpc:arm64-windows
vcpkg install grpc --triplet arm64-uwp

Not sure which one should suite, but getting the same DllNotFound exception with both.

@veronicagarciavazquez
Copy link

Thanks! I will try it. Please see my comment on, I think, your other thread:

https://forum.unity.com/threads/hololens2-with-grpc-on-unity.932688/

I hope that your error is solved with /MT

@tom-r-o
Copy link
Author

tom-r-o commented Jul 19, 2020

Yes, that was another thread I opened :)
And yes, the "/MT" flag made the single function C++ DLL work on HoloLens2.
So your conclusion is correct - it must be an issue with the compiled grpc_csharp_ext.dll that I'm using.

Please let me know if you manage to get it working.

@veronicagarciavazquez
Copy link

veronicagarciavazquez commented Jul 21, 2020

Trying #20344 (comment) but I got stuck in

python tools/run_tests/run_tests.py -l csharp -c opt --build_only

Did you have the following error when doing tools\run_tests\helper_scripts\build_csharp.bat (I am using Visual Studio 16 2019)?

C:\Users\XX\.nuget\packages\microsoft.build.tasks.git\1.0.0-beta2-18618-05\build\Microsoft.Build.Tasks.Git.targets(20,5): error MSB4018: task failed unexpectedly "Microsoft.Build.Tasks.Git.LocateRepository". [C:\HoloLens2_projects\grpc_buildCommit\grpc\src\csharp\Grpc.Core.Api\Grpc.Core.Api.csproj]

\r\nC:\Users\XX\.nuget\packages\microsoft.build.tasks.git\1.0.0-beta2-18618-05\build\Microsoft.Build.Tasks.Git.targets(20,5): error MSB4018: System.TypeInitializationException: The type initializer for 'Microsoft.Build.Tasks.Git.TaskImplementation' threw an exception. [C:\HoloLens2_projects\grpc_buildCommit\grpc\src\csharp\Grpc.Core.Api\Grpc.Core.Api.csproj]

\r\nC:\Users\XX\.nuget\packages\microsoft.build.tasks.git\1.0.0-beta2-18618-05\build\Microsoft.Build.Tasks.Git.targets(20,5): error MSB4018: ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Build.Tasks.Git, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. System cannot find the specific file

....

@tom-r-o
Copy link
Author

tom-r-o commented Jul 22, 2020

Not sure if it'll solve your issue, but in one of the builds based on #20344 (comment) I noticed an error that was related to an older VS version, so I installed VS2015 and used its "developer command prompt" to run the build (which worked).

The side effect was that it had mixed up global VS variables, and I had to re-install windows to get vcpkg working again.
So if you have multiple machines or a VM I'd recommend doing the build on such a machine.

@veronicagarciavazquez
Copy link

By the way, I attended the gRPC Conf 2020.

I asked the following question in the session "Ask Us Anything: gRPC Maintainers":

Trying to use gRPC on HoloLens 2 (ARM64). I use Unity 2019.3 to build the Visual studio project. Unity uses .NET 4.x or .NET standard 2.0, with IL2CPP backend. Do you think that grpc-dotnet will work on HoloLens 2? If not, do you have any suggestion with grpc.core? With grpc.core I could built grpc_csharp_ext.dll for ARM64 using vcpkg but it does not work because I need to build it with the option /MT.

Their answer:

Grpc.Core might also not work unfortunately, because we only support Unity as "experimental" and there is way too many targeted platforms for us to test. I don't think there's anything preventing your from using Grpc.Core (C#) with HoloLens in principle, but you might need to tweak the source code a bit to make that work. - Jan Tattermusch

grpc-dotnet will very likely not work with Unity because unity doesn't support recent .NET core versions. (you'd need netstandard2.1/netcoreapp3.0 to use grpc-dotnet) - Jan Tattermusch

@ras0219
Copy link

ras0219 commented Aug 12, 2020

You could try using a custom triplet[1] to build with /MT

set(VCPKG_CRT_LINKAGE static)

[1] https://github.com/microsoft/vcpkg/tree/master/docs/users/triplets.md

@veronicagarciavazquez
Copy link

veronicagarciavazquez commented Aug 26, 2020

I cloned vcpkg repository on 15.07.2020. With that version, I can generate grpc_csharp_ext.dll with the triplet arm64-windows as tom-r-o suggested. After creating a custom triplet for arm64-windows with the setting that ras0219 suggested for building with /MT (thanks!), I can also generate grpc_csharp_ext.dll. In that case, the gRPC version is 1.29.1. However, if I try to generate grpc_csharp_ext.dll with the triplet arm64-windows (without /MT) after cloning the vcpkg repository today (version of gRPC 1.31.1), I have grpc_csharp_ext.lib but not grpc_csharp_ext.dll, no error shown. I do not know why because the triplet of the new version of vcpkg matches that of the old version.

The reason for updating vcpkg (and thus grpc) is because I think I also have a problem with the grpc versions. I implemented a grpc server with the NuGet packages Google.Protobuf (version 3.13.0) and Grpc.Core (version 2.30.0) with Visual Studio 2019. Same NuGet packages for the Unity project using MSBuild for Unity (package manager). I can receive the data in Unity from the gRPC server using these settings but if I just replace grpc_csharp_ext.dll that comes with MSBuild with a new grpc_csharp_ext.dll generated with vcpkg (grpc version 1.29.1) and the triplet x64-windows, Unity says that "DllNotFoundException: grpc_csharp_ext". Do you know which version of the NuGet packages Google.Protobuf and Grpc.Core will work with which version of grpc to generate grpc_csharp_ext.dll with vcpkg?

tom-r-o , in your Unity project have you tried to replace grpc_csharp_ext.dll with a dll generated with vcpkg (x64) to check if you do not have any problem with the versions, at least for x64?

@veronicagarciavazquez
Copy link

veronicagarciavazquez commented Aug 28, 2020

Regarding the versions problem, I could generate a grpc_csharp_ext.dll for x64 that works with the NuGet packages Google.Protobuf (version 3.13.0) and Grpc.Core (version 2.30.0) (using MSBuild for Unity (package manager)) in Unity. What I did was to clone the version of gprc 1.31.1 and follow the steps in https://github.com/grpc/grpc/blob/v1.31.1/BUILDING.md (Windows, CMake) except for using

cmake .. -G "Visual Studio 15 2017" -A x64

Now the next steps would be to generate grpc_csharp_ext.dll for ARM64 using the same way as before and try to do the same as #20344 (comment) (tom-r-o suggestion) but with the version of grpc corresponding to the NuGet packages.

I have started with the first step (generate the ARM64 file for grpc_csharp_ext.dll)

cmake .. -G "Visual Studio 15 2017" -A ARM64

and I have the following errors:

crypto.dir\Release\chacha-x86_64.obj : fatal error LNK1112: module machine type 'x64' conflicts with target machine typ
e 'ARM64' [C:\grpc.buildARM64\third_party\boringssl-with-bazel\crypto.vcxproj]

No idea yet how to create chacha.obj for ARM64

and

C:\grpc\src\core\lib\transport\transport.cc(100): warning C4003: not enough arguments for function-like macro invocatio
n 'move64' [C:\grpc.buildARM64\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(100): error C2065: 'opeqneoneg': undeclared identifier [C:\grpc.buildARM64
\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(100): error C2065: 'to': undeclared identifier [C:\grpc.buildARM64\grpc_un
secure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(100): error C2275: 'uint64_t': illegal use of this type as an expression [C
:\grpc.buildARM64\grpc_unsecure.vcxproj]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\stdint.h(24): note: s
ee declaration of 'uint64_t'
C:\grpc\src\core\lib\transport\transport.cc(100): error C2059: syntax error: ',' [C:\grpc.buildARM64\grpc_unsecure.vcx
proj]
C:\grpc\src\core\lib\transport\transport.cc(100): error C2143: syntax error: missing ';' before '{' [C:\grpc.buildARM6
4\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(100): error C2447: '{': missing function header (old-style formal list?) [C
:\grpc.buildARM64\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(107): warning C4003: not enough arguments for function-like macro invocatio
n 'move64' [C:\grpc.buildARM64\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(107): error C2065: 'opeqneoneg': undeclared identifier [C:\grpc.buildARM64
\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(107): error C2059: syntax error: ',' [C:\grpc.buildARM64\grpc_unsecure.vcx
proj]
C:\grpc\src\core\lib\transport\transport.cc(108): warning C4003: not enough arguments for function-like macro invocatio
n 'move64' [C:\grpc.buildARM64\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(108): error C2065: 'opeqneoneg': undeclared identifier [C:\grpc.buildARM64
\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(108): error C2059: syntax error: ',' [C:\grpc.buildARM64\grpc_unsecure.vcx
proj]
C:\grpc\src\core\lib\transport\transport.cc(109): warning C4003: not enough arguments for function-like macro invocatio
n 'move64' [C:\grpc.buildARM64\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(109): error C2065: 'opeqneoneg': undeclared identifier [C:\grpc.buildARM64
\grpc_unsecure.vcxproj]
C:\grpc\src\core\lib\transport\transport.cc(109): error C2059: syntax error: ',' [C:\grpc.buildARM64\grpc_unsecure.vcx
proj]

Any suggestion?

@veronicagarciavazquez
Copy link

veronicagarciavazquez commented Sep 1, 2020

Regarding chacha.obj for ARM64, I have had a look at cMakeLists.txt in cypto project.

There are ASM files for win-x86 and win-86-64 in grpc\third-party\boringssl-withbazel. For ARM64 there are files for Linux and iOS (see below) but not for windows...

grpc\third_party\boringssl-with-bazel\ios-aarch64\crypto\chacha\chacha-armv8.S
grpc\third_party\boringssl-with-bazel\linux-aarch64\crypto\chacha\chacha-armv8.S

Any suggestion to get through this problem? I think I will have the same problem for the other ASM files:

win-x86_64/crypto/chacha/chacha-x86_64.asm
win-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.asm
win-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.asm
win-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.asm
win-x86_64/crypto/fipsmodule/aesni-x86_64.asm
win-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.asm
win-x86_64/crypto/fipsmodule/ghash-x86_64.asm
win-x86_64/crypto/fipsmodule/md5-x86_64.asm
win-x86_64/crypto/fipsmodule/p256-x86_64-asm.asm
win-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.asm
win-x86_64/crypto/fipsmodule/rdrand-x86_64.asm
win-x86_64/crypto/fipsmodule/rsaz-avx2.asm
win-x86_64/crypto/fipsmodule/sha1-x86_64.asm
win-x86_64/crypto/fipsmodule/sha256-x86_64.asm
win-x86_64/crypto/fipsmodule/sha512-x86_64.asm
win-x86_64/crypto/fipsmodule/vpaes-x86_64.asm
win-x86_64/crypto/fipsmodule/x86_64-mont.asm
win-x86_64/crypto/fipsmodule/x86_64-mont5.asm
win-x86_64/crypto/test/trampoline-x86_64.asm

@aleneum
Copy link

aleneum commented Sep 10, 2020

I managed to get grpc 1.25 working on HoloLens 2. I also tried the most recent version (1.29.1) vcpkg has to offer but unfortunately there is a Protobuf/System.Memory version conflict (#22251) which hasnt been resolved yet, afaik. The referenced issues claims that the last version without that conflict has been 1.26 which -- as I mentioned in my previous comment -- contains a grpc_csharp_ext.dll which my HoloLens at least isnt detecting.

So what needs to be done:

  • I basically followed Unity build linker error for Windows Standalone/HoloLens 1 & 2 ( x86 & x86_64 ) #20344 (comment)
  • If you are like me and don't want to install outdated build tools you can change the used Visual Studio version in tools\run_tests\helper_scripts\pre_build_csharp.bat. I used "Visual Studio 15 2017" instead of "Visual Studio 14 2015".
  • Make sure to clean the cmake\build folder if you ran run_tests.py before
  • If everything works well, you will end up with some Microsoft.Build.Tasks.Git.targets exceptions when the Python script attempts to build the C# project. It's probably related to some outdated SourceLink dependency or something. Nevertheless, the project will build just fine with Visual Studio 2019 when you use the Grpc.sln file.
  • If you followed these steps, you should have something that works with Unity and HoloLens 1, now the part that makes it work with HoloLens2. A big thank you goes to @tom-r-o: The vcpkg hint in combination with triplets was the decisive factor to get it running. Without the idea of building a static version of grpc_csharp_ext.dll by @veronicagarciavazquez I'd still wondering why stuff isn't working. Thank you to both of you for sharing your experiences!
  • Clone vcpkg and checkout the tag 2020.01. I don't know whether checking out 2020.01 is actually necessary but it contains the grpc version closest to 1.25
    • git clone https://github.com/microsoft/vcpkg.git
    • git checkout 2020.01
  • You have to edit the grpc port to build the correct version. Download 00001-fix-uwp.patch.txt, 00002-static-linking-in-linux.patch.txt and portfile.cmake.txt, remove the .txt ending and override the files located at ports\grpc.
  • Next you have to backport a triplet configuration: Download arm64-windows-static.cmake.txt, rename it and put it into triplets\community
  • Now bootstrap vcpkg and build protobuf:x86-windows and grpc with the arm64-windows-static triplet
    • .\vcpkg.exe install protobuf:x86-windows
    • .\vcpkg.exe install grpc --triplet arm64-windows-static
  • Copy the generated file buildtrees\grpc\arm64-windows-static-rel\grpc_csharp_ext.dll into your Plugin folder (Grpc.Core\runtimes\win\arm64) and set the target for this DLL:
    arm64_ext

@veronicagarciavazquez
Copy link

veronicagarciavazquez commented Sep 10, 2020

@aleneum, Great that gRPC 1.25 is working on HoloLens 2 with the vcpkg and the unity package!!!! Congratulations and also thanks for your ideas of last year!! In my case I couldn't make it run using vcpkg. Thanks! I found that idea about the dll here. I would like also to thank @tom-r-o.

I have been able to make gRPC (version 1.31.1) run on HoloLens 2 this week directly with gRPC github repository as follows:

  1. To clone and generate grpc_csharp_ext.dll on Windows you need first to follow the steps detailed in https://github.com/grpc/grpc/blob/v1.31.1/BUILDING.md and some other steps. I did that on a virtual machine Windows 10 (64-bit) with Oracle VM VirtualBox not to have any problem with my Visual Studio 2019 installed on my computer as @tom-r-o suggested me. Basically:
  • Install Visual Studio 2017
  • Install Git
  • Install CMake
  • Install Chocolatey
  • Install nasm (choco install nasm), check that it is added to PATH
  • In CMD:
cd c:\
git clone -b v1.31.1 https://github.com/grpc/grpc
cd grpc
git submodule update --init
md .build_ARM64
cd .build_ARM64
cmake .. -G "Visual Studio 15 2017" -A ARM64 -D OPENSSL_NO_ASM=1

With OPENSSL_NO_ASM=1 the build does not use ASM files (contain lines of code in assembly language). I did that because there are not ASM files for ARM64 in gRPC repository, specifically in c:\grpc\third_party\boringssl-with-bazel (there are ASM files for Windows x86 and x86_64). I have no idea yet how to generate those ASM files for ARM64.

  • Open C:\grpc.build_ARM64\grpc.sln in Visual studio 2017.
  • Change to Release.
  • Replace in transport.cc (grpc_csharp_ext.dll for ARM64 is not created without this change):
static void move64(uint64_t* from, uint64_t* to) {
  *to += *from;
  *from = 0;
}

void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats* from,
                                       grpc_transport_one_way_stats* to) {
  move64(&from->framing_bytes, &to->framing_bytes);
  move64(&from->data_bytes, &to->data_bytes);
  move64(&from->header_bytes, &to->header_bytes);
}

with

static void move64_aux(uint64_t* from, uint64_t* to) {
  *to += *from;
  *from = 0;
}

void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats* from,
                                       grpc_transport_one_way_stats* to) {
  move64_aux(&from->framing_bytes, &to->framing_bytes);
  move64_aux(&from->data_bytes, &to->data_bytes);
  move64_aux(&from->header_bytes, &to->header_bytes);
}
  • Select all projects except ALL_BUILD, Continuous, Experimental, INSTALL, Nightly, NightlyMemoryCheck, plugins, tools, tools_c, tools_cxx, ZERO_CHECK and go to Properties -- C/C++ -- Code Generation -- Runtime Library: Multi-threaded (/MT) -- OK.
  • Select project grpc_csharp_ext and Build. When it finishes, you have C:\grpc.build_ARM64\Release\grpc_csharp_ext.dll for ARM64.
  1. Then, in my computer (where I have Visual Studio 2019), I did the following steps to create a folder with all necessary gRPC files for Unity:
  • Create folder c:\gRPC_Unity_1_31_1 and inside create these folders
c:\gRPC_Unity_1_31_1\Plugins\Win32\x86
c:\gRPC_Unity_1_31_1\Plugins\Win32\x86_64
c:\gRPC_Unity_1_31_1\Plugins\Win32\ARM64
  • In Visual Studio 2019, create a new project (Name: Example) -- Filters c#, Windows, Console -- Choose Console App (.NET Framework) -- Select Framework: .NET Framework 4.5 -- Select project -- Manage NuGet Packages -- Install Google.Protobuf (version 3.13.0), package Grpc.Core (version 2.31.0) and Grpc.Tools (version 2.31.0). After this step, you will find in C:\Users\XXXX.nuget\packages\grpc.tools\2.31.0 the files protoc.exe and grpc_csharp_plugin.exe to generate two specific .cs files (I will refer them to YYpackage.cs and YYGrpc.cs) from the proto file. You do not need to generate those files yet. Build solution.
  • Copy the following dlls from Example\Example\bin\Debug to C:\gRPC_Unity_1_31_1\Plugins\Win32
Google.Protobuf.dll
System.Buffers.dll
System.Memory.dll
System.Runtime.CompilerServices.Unsafe.dll
  • Copy Example\Example\bin\Debug\grpc_csharp_ext.x86.dll to c:\gRPC_Unity_1_31_1\Plugins\Win32\x86 and rename this file to grpc_csharp_ext.dll
  • Copy Example\Example\bin\Debug\grpc_csharp_ext.x64.dll to c:\gRPC_Unity_1_31_1\Plugins\Win32\x86_64 and rename this file to grpc_csharp_ext.dll
  • Copy grpc_csharp_ext.dll that you generated in step 1 to c:\gRPC_Unity_1_31_1\Plugins\Win32\ARM64
  • Going back to the folder were you have downloaded the GitHub repository (Virtual machine, C:\grpc), go to C:\grpc\src\csharp and copy Grpc.Core and Grpc.Core.Api folders to c:\gRPC_Unity_1_31_1.
  • In c:\gRPC_Unity_1_31_1, remove all files except for cs files (for example Grpc.Core\build folder is deleted). Copy the content of Grpc.Core.Api into Grpc.Core except for Grpc.Core.Api\Properties\AssemblyInfo.cs (keep file from Grpc.Core) and Grpc.Core.Api\Internal\UnimplementedCallInvoker.cs (same file in both folders). In c:\gRPC_Unity_1_31_1, remove Grpc.Core.Api folder and Grpc.Core\ForwardedTypes.cs file.
  • Finally, copy the content of C:\gRPC_Unity_1_31_1 to the Assets folder of a Unity project configured for HoloLens 2 (I did not include MRTK in that Unity project).
  1. In Unity
  • Select Assets\Plugins\w32\x86_64\grpc_csharp_ext.dll, Select just platform Editor, CPU: x86_64, OS: Windows, Apply
  • Select Assets\Plugins\w32\x86\grpc_csharp_ext.dll, Select just platform WSAPlayer, SDK: UWP, CPU: X86, Apply
  • Select Assets\Plugins\w32\ARM64\grpc_csharp_ext.dll, Select just platform WSAPlayer, SDK: UWP, CPU: ARM64, Apply
  • Go to Player Settings -- Other Settings -- Enable "Allow 'unsafe code'".

Change the following cs files (you can see why I have done that change in the comments):

  • Go to line 49 in Assets\Grpc.Core\Internal\NativeExtension.cs and do this change
    // DefaultSslRootsOverride.Override(this.nativeMethods); // (commented to fix IOException: Error loading the embedded resource "Grpc.Core.roots.pem")
  • In Assets\Grpc.Core\Internal\NativeMethods.Generated.cs, go to line 584 and do these changes
//private const string ImportName = "__Internal"; // (commented)
private const string ImportName = "grpc_csharp_ext.dll"; // (added, lines 584-585 fixes Visual Studio error Error LNK2019 unresolved external symbol grpcsharp_version_string referenced in function DllImportsFromStaticLib_grpcsharp_version_string_m9DB1E4C23A3BD8941C1EA0D157230C0C15F5E13A	Il2CppOutputProject". DllImport does not work with __Internal in Il2Cpp
  • In Assets\Grpc.Core\Internal\NativeExtension.cs, go to line 132 and do these changes
//switch (PlatformApis.GetUnityRuntimePlatform()) // (commented, PlatformApis.GetUnityRuntimePlatform() does not work on HoloLens 2)
//{ // (commented)
//    case "IPhonePlayer": // (commented)
//        return new NativeMethods(new NativeMethods.DllImportsFromStaticLib()); // (commented)
//    default: // vgarcia (commented)
//        // most other platforms load unity plugins as a shared library // (commented)
//        return new NativeMethods(new NativeMethods.DllImportsFromSharedLib()); // (commented)
//} // (commented)
return new NativeMethods(new NativeMethods.DllImportsFromSharedLib()); // (added)
  • In Assets\Grpc.Core\Internal\UnmanagedLibrary.cs, go to line 132 and do these changes
//private static class Mono // (commented, to fix unresolved external symbol dlopen, dlerror and dlsym in Visual Studio)
//{ // (commented)
//    [DllImport("__Internal")] // (commented)
//    internal static extern IntPtr dlopen(string filename, int flags); // (commented)

//    [DllImport("__Internal")] //  (commented) 
//    internal static extern IntPtr dlerror(); // (commented)

//    [DllImport("__Internal")] // (commented)
//    internal static extern IntPtr dlsym(IntPtr handle, string symbol); //  (commented)
//} // (commented)
  • After that go to line 100 (Assets\Grpc.Core\Internal\UnmanagedLibrary.cs) and do
    // return Mono.dlsym(this.handle, symbolName); // (commented, name 'Mono' does not exist in the current context Assembly-CSharp
  • After that go to line 146 (Assets\Grpc.Core\Internal\UnmanagedLibrary.cs) and do
// return LoadLibraryPosix(Mono.dlopen, Mono.dlerror, libraryPath, out errorMsg); // commented, name 'Mono' does not exist in the current context Assembly-CSharp
throw new NotImplementedException("Mono is not supported by this build"); // (added)

  • Now you can create a Unity package that you can import in each Unity project that you need gRPC. In Unity, Assets -- Select Grpc.Core and Plugins -- Right mouse button -- Export package -- Unselect Include dependencies -- Export -- I named it GRPC_version_1_31_1_csharpNuGet_2_31_0_HoloLens2.unitypackage

To load this Unity package to another Unity project, Assets -- Import package -- Custom package -- Select GRPC_version_1_31_1_csharpNuGet_2_31_0_HoloLens2.unitypackage -- Import
Go to Player Settings -- Other Settings -- Enable "Allow 'unsafe code'". You will find all files (cs files, managed plugins [Google.Protobuf.dll, System.Buffers.dll, System.Memory.dll, System.Runtime.CompilerServices.Unsafe.dll] and native plugins [ARM64\grpc_csharp_ext.dll, x86\grpc_csharp_ext.dll, x86_64\grpc_csharp_ext.dll]) with the right settings. The last thing that you need in your new Unity project is to load YYpackage.cs and YYGrpc.cs generated from your proto file and the .cs file where you do gRPC stuff like...

Channel channel = new Channel("192.168.1.90:50051", ChannelCredentials.Insecure);
YYpackage.YYpackage.YYpackageClient client; = new YYpackage.YYpackage.YYpackageClient(channel);
...

After the application works on Unity editor, in Unity generate Visual Studio solution, open it with Visual Studio 2019, change to ARM64 and Deploy Solution to HoloLens 2.

IMPORTANT NOTES:

  1. I need "ChannelCredentials.Insecure" because I commented "DefaultSslRootsOverride.Override(this.nativeMethods)" since I could not load resource "Grpc.Core.roots.pem" (that file corresponds to c:\grpc\etc\roots.pem). I tried several things (for example gRPC + IL2CPP for Unity fails to build #22485 but I could not load that file. Not sure what I am doing wrong.
  2. The dll I generated for ARM64 does not use ASM files. In boringssl: Compiling with OPENSSL_NO_ASM harms throughput of secure connections significantly #9440 they explain that compiling with OPENSSL_NO_ASM harms throughput of secure connections significantly. I am still need to check the latencies (maybe comparing with the latencies with HoloLens 1 and GRPC_version_1_31_1_csharpNuGet_2_31_0_HoloLens2.unitypackage [grpc_csharp_ext.dll for x86 is also included in that package]). In my case I am not using a secure connection. Anyway, it would be great to have those ASM files for ARM64...

@stale
Copy link

stale bot commented Dec 10, 2020

This issue/PR has been automatically marked as stale because it has not had any update (including commits, comments, labels, milestones, etc) for 30 days. It will be closed automatically if no further update occurs in 7 day. Thank you for your contributions!

@aleneum
Copy link

aleneum commented Dec 10, 2020

Is there a more streamlined way than what @veronicagarciavazquez outlines? It's great that it actually works but it could be easier imho. I still think this is has not been solved so far.

@stale stale bot removed the disposition/stale label Dec 10, 2020
@Birkenpapier
Copy link

Birkenpapier commented Jan 11, 2021

@veronicagarciavazquez, thank you very much for your indepth tutorial of deploying gRPC on the HL2!
Sadly it did not worked on the HL2. The unitypackage I've created is working flawlessly and fast on the editor but when I create a solution for the HL2 and deploy it I ran into two errors.
The first error comes when I use IP addresses that the server can't be found and failed to pick subchannel. To exclude HL2 connection issues I've set up a gRPC server behind public URL and then tested it again. The error now comes after 60s (timeout?) that the DNS cannot be resolved.
Did you or anybody encouter same/similar problems and managed to solve/work around them?

@Birkenpapier
Copy link

I found the location of the problem!

I created the solution always for ARM64 in the build settings in unity.
In order to solve this issue it needs (at least for me) to be build for ARM and then, just like @veronicagarciavazquez said, ARM64 needs to be selected in VS2019. Then the Hololens 2 can connect to the gRPC server.
I also confirmed that gRPC can be build with VS2019 instead of VS2017 in the first step of the explanation from @veronicagarciavazquez.

I hope everybody manage to run gRPC on Hololens 2 and don't have annoying blockers.

Thank you very much!

@Walkramis
Copy link

Thank you @veronicagarciavazquez for the amazing explanation! I have now also managed to build it, but I am having similar problems as @Birkenpapier . I am getting an error saying that the server cannot be found and failed to pick subchannel. @Birkenpapier I tried to do what you did but without success. Would you mind giving a litte bit deeper explanation? It is working in unity, android, other computer etc. so I have ruled out error on the server side.

@vgarciavazquez
Copy link

Just in case, my settings in Unity were as follows:

Unity (version Unity 2019.3.15f1 (64-bit))
Projects -- New -- Project Name: XX -- 3D
File -- Build Settings:

  • Add Open Scenes
  • Universal Windows Platform -- Switch Platform
  • Target device -- HoloLens
  • Architecture -- ARM64
  • Development Build enabled
  • Script Debugging enabled
  • Press Player Settings (settings for Universal Windows Platform) and in Publishing Settings:
    -- Capabilities, enable the following ones:
    ----- Internet Client
    ----- InternetClientServer (for debugging)
    --- PrivateNetworkClientServer (for debugging)
  • In XR Plugin Management, enable the following ones:
    -- Install XR Plugin Management
    ----- Enable Windows Mixed Reality (in windows tab)

@Birkenpapier
Copy link

Birkenpapier commented Mar 7, 2021

Thank you @veronicagarciavazquez for the amazing explanation! I have now also managed to build it, but I am having similar problems as @Birkenpapier . I am getting an error saying that the server cannot be found and failed to pick subchannel. @Birkenpapier I tried to do what you did but without success. Would you mind giving a litte bit deeper explanation? It is working in unity, android, other computer etc. so I have ruled out error on the server side.

Of course. I will try to explain it deeper:

The server and one client are written in Python 3.8.5. The server is receiving messages from the Python client and then wating for a message from the HoloLens client to send the message.
My HoloLens client is based on this example here: https://shadabambat1.medium.com/basic-client-server-communication-using-unity-grpc-f4a3c2cf819c

This are my deploying options in Unity 2019.4.17f1
grafik

and here in VS 2019:
grafik

I hope that something helped in this explanation.

Edit:
Maybe it is alwo worth to have a look at the "capabilites" section in the player settings before deployment.
I have selected everything that could be used for internet connections.

@Walkramis
Copy link

Thank you both for spending time to help! As you both pointed out I had made the mistake of forgetting to add the correct capabilities... But now it's working so thanks once again since I probably would have spent another couple of days fault tracing before I would have remembered to look at the capabilities :)

@jtattermusch
Copy link
Contributor

Since Grpc.Core is now in maintenance mode (see https://grpc.io/blog/grpc-csharp-future/), we don't plan to add any new features (or add support for more platforms).

@HaiKonofanDesu
Copy link

HaiKonofanDesu commented Oct 24, 2022

@veronicagarciavazquez

Seems like I actually got the files compiled myself now thanks to your explanation (had 2 problems which are my fault tho, did not rename the .dll's properly and had a .asmdef file in my script folder which made it that my code could not find the Grpc namespace). At least an empty project with just these files works just fine to build and deploy.

But I still get an error when I try to deploy my stuff to the HoloLens:

image

Any ideas how to fix it?

EDIT:
Seems like the problem are my generated .cs files (from the .proto files). Can someone eplain in more details how they generated their files? dotnet build csharp did not work for me (just have the .proto files). I instead did it like it's descibed here:
https://shadabambat1.medium.com/basic-client-server-communication-using-unity-grpc-f4a3c2cf819c but seems like Unityy/ VS does not like this way?

@Birkenpapier @Walkramis How did you generate your c# files?

EDIT2: Using Unity 2020 or 2019 removed the error for me so it's a Unity 2021 (maybe 2022 as well?) bug. Now I can deploy the app but still get the Error that it can't reach the adresses. Not sure if that's a firewall problem of my working laptop or not. Dependencies are all active. Will update this post once I know more.

@vgarciavazquez
Copy link

Great the error was removed with Unity 2020/2019. Sorry, I do not know why it cannot reach your address and I cannot test it with a HoloLens right now... :-(

Maybe one option is to try to create a x64 application with Unity to test if you can receive the data on another computer (not on Hololens) sent by your laptop.

@SnowWindSaveYou
Copy link

follow the step but not found such a dll

@HaiKonofanDesu
Copy link

Great the error was removed with Unity 2020/2019. Sorry, I do not know why it cannot reach your address and I cannot test it with a HoloLens right now... :-(

Maybe one option is to try to create a x64 application with Unity to test if you can receive the data on another computer (not on Hololens) sent by your laptop.

Thanks for the tip! I moved the server to a different PC and it worked! Seems like the Company Firewall does not allow any device outside the company internet to connect to the PC so that is probably the problem.

Unity Support also said that my code works for them on Unity 2021 with the newest version but does not work for me. Maybe this Info helps someone as they are at least working on it?

@SnowWindSaveYou Here is my grpc stuff as a Unity Package. Best way to try it is to download this repo and if this does not work change the grpc stuff with my stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests