Here, or here for a complete version, you can find a sample GRPC "Hello World" project for Unity. Only the first version, that is built for Unity and wrapped in a DLL is working perfectly fine in Unity IDE and on Standalone build. The Raw Grpc.Core files are referencing everything correctly in IDE but they have Marshaling problem.
Unfortunately, it cannot get build for UWP with IL2CPP backend. Unity builds the project and creates a .sln project. But Visual Studio always gives LNK2001 for GRPC properties on the final compilation.
Here are first error codes:
LNK2001 unresolved external _grpccsharp_init#0
LNK2001 unresolved external _grpccsharp_shutdonw#0
LNK2001 unresolved external _grpccsharp_version_string#0
...
Ok, thanks to #Sunius, I digged into it a little bit more. There are some points, I am going to add to the question:
There are two methods regarding referencing extern methods in GRPC C# package. They are named static and shared libs.
internal class DllImportsFromStaticLib
{
private const string ImportName = "__Internal";
[DllImport(ImportName)]
public static extern void grpcsharp_init();
[DllImport(ImportName)]
public static extern void grpcsharp_shutdown();
...
}
and
internal class DllImportsFromSharedLib
{
private const string ImportName = "grpc_csharp_ext";
[DllImport(ImportName)]
public static extern void grpcsharp_init();
[DllImport(ImportName)]
public static extern void grpcsharp_shutdown();
...
}
I tried to test it with the shared one, I got another linking error file which is a little bit different.
LNK2001 unresolved external _dlopen#8
LNK2001 unresolved external _dlsym#8
...
In two separate methods, extern methods are getting connected to the internal interface:
public NativeMethods(DllImportsFromStaticLib unusedInstance)
{
this.grpccsharp_init = DllImportsFromStaticLib.grpccsharp_init;
this.grpccsharp_shutdown = DllImportsFromStaticLib.grpccsharp_shutdonw;
...
}
and
public NativeMethods(DllImportsFromSharedLib unusedInstance)
{
this.grpccsharp_init = DllImportsFromSharedLib.grpccsharp_init;
this.grpccsharp_shutdown = DllImportsFromSharedLib.grpccsharp_shutdonw;
...
}
And which method will get called is defined here:
private static NativMethods LoadNativeMethodsUnity()
{
switch(PlatformApis.GetUnityRuntimePlatform())
{
case "IPhonePlayer":
return new NativeMethods(new NativeMethods.DllImportsFromStaticLib());
default:
return new NativeMethods(new NativeMethods.DllImportsFromSharedLib());
}
}
Some updates:
Thanks to #jsmouret, there is Stub.c file in his Grpc Github with fake methods, so Linker does not complain about Grpc_init methods anymore.
Next Error: dlopen, dlsym, dlerror:
First, I tried to use the same, Stub technique, but it did not help in this case, or maybe I did it wrong.
Thanks to #Sunius, I commented out all of "__Internal" dll import codes. So I am not getting any dlopen, dlsym, and dlerror errors.
Next Error: It happens from inside application, not the visual studio debugger. It tells me: "exception: to marshal a managed method, please add an attribute named 'MonoPInvokeCallback' to the method definition."
exception: error loading the embedded resource "Grpc.Core.roots.pem"
and
exception: To marshal a managed method, please add an attribute named 'MonoPInvokeCallback' to the method definition.
After I googled it, I know my options, but the question it, for which method should I do that?!
Thanks to my colleague Alice, #Sunius and #jsmouret, at the end, grpc works on UWP on Unity Platform through this steps:
Download Grpc.Core folder from Google Grpc Github.
Download Grpc Unity plugin from their official site.
Copy the runtime folder to your Grpc.Core folder. Please remove Grpc.Core.dll that you get from Grpc Unity Plugin, since we are using their source code.
Grpc should be in a folder called, Plugins in Unity, otherwise it will not be recognized.
Include this file in your runtime folder.
Include the Stub also from the Unity Plugin Inspector for WSA.
Find runtime .dll for Windows and include them in WSA from Unity Plugin Inspector.
By now, you should be getting _dlopen error.
Search through your Unity Solution with an IDE for "__Internal". There are not so many places, but comment them out. Also some methods that are depended on "__Internal"s, like dlopen and dlsym.
By now, you are not getting anymore build error but you need to make Grpc work.
Search for something like "DefaultSslRootsOverride" and comment out like below:
internal static class DefaultSslRootsOverride
{
const string RootsPemResourceName = "Grpc.Core.roots.pem";
static object staticLock = new object();
/// <summary>
/// Overrides C core's default roots with roots.pem loaded as embedded resource.
/// </summary>
public static void Override(NativeMethods native)
{
lock (staticLock)
{
//var stream = typeof(DefaultSslRootsOverride).GetTypeInfo().Assembly.GetManifestResourceStream(RootsPemResourceName);
//if (stream == null)
//{
// throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", RootsPemResourceName));
//}
//using (var streamReader = new StreamReader(stream))
//{
// var pemRootCerts = streamReader.ReadToEnd();
// native.grpcsharp_override_default_ssl_roots(pemRootCerts);
//}
}
}
}
Search for something like "static void HandWrite" and add an attribute like something in below:
[MonoPInvokeCallback(typeof(GprLogDelegate))]
private static void HandleWrite(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr)
{
try
{
var logger = GrpcEnvironment.Logger;
string severityString = Marshal.PtrToStringAnsi(severityStringPtr);
string message = string.Format("{0} {1}:{2}: {3}",
threadId,
Marshal.PtrToStringAnsi(fileStringPtr),
line,
Marshal.PtrToStringAnsi(msgPtr));
switch (severityString)
{
case "D":
logger.Debug(message);
break;
case "I":
logger.Info(message);
break;
case "E":
logger.Error(message);
break;
default:
// severity not recognized, default to error.
logger.Error(message);
break;
}
}
catch (Exception e)
{
Console.WriteLine("Caught exception in native callback " + e);
}
}
I guess, you are done. In case, it did not work for your UWP, let me know, maybe I can help. :)
It looks like your plugin uses "__Internal" P/Invoke to call those native functions:
https://github.com/grpc/grpc/blob/befc7220cadb963755de86763a04ab6f9dc14200/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs#L542
However, the linker cannot locate those functions and thus fails. You should change that code to either specify the DLL file name where the functions are implemented, or drop the source files with definitions for those functions into your Unity project. Or, if that code path isn't actually invoked (since you said it works on the standalone player), #ifdef it out from UWP build.
You can find more information about "__Internal" P/Invoke here:
https://docs.unity3d.com/Manual/windowsstore-plugins-il2cpp.html
I'm developping an app with OpenFrameworks with C++ language.
In my program there is a line that makes a dynamic cast pointer
Ref_<ImageUniform> p = o.cast<ImageUniform>();
Here is the class that implementing the cast() function implementation
template <typename T>
struct Ref_ : public ofPtr<T>
{
Ref_() {}
Ref_(T *t) : ofPtr<T>(t) {}
Ref_(const Ref_<T>& o) : ofPtr<T>(o) {}
Ref_(const ofPtr<T>& o) : ofPtr<T>(o) {}
template <typename TT>
Ref_<TT> cast() const { return dynamic_pointer_cast<TT>(*this); }
};
When I compile without the -std=c++11 it works.
But when I put the -std=c++11 it prints me a compile error and refers me to an internal file "ofTypes.h" of the library of OpenFrameworks at this line 191:
#else
template<typename Tp1>
ofPtr(const ofPtr<Tp1>& __r, std::__dynamic_cast_tag)
: std::shared_ptr<T>(__r, std::__dynamic_cast_tag()) { }
#endif
And also here is the compile error
......\libs\openFrameworks\types\ofTypes.h|193|error: no matching function >for call to 'std::shared_ptr::shared_ptr(const >ofPtr&, std::tr1::__dynamic_cast_tag)'|
#else
template
ofPtr(const ofPtr& __r, std::__dynamic_cast_tag)
: std::shared_ptr(__r, std::__dynamic_cast_tag()) { }
#endif
Either you should update your version of OpenFrameworks (which supports C++11), or you should not compile current code with C++11.
Now you have problem with below code
template<typename Tp1>
ofPtr(const ofPtr<Tp1>& __r, std::__dynamic_cast_tag)
: std::shared_ptr<T>(__r, std::__dynamic_cast_tag()) { }
when you compile this code without C++11, implementation of shared_ptr is taken from tr1/memory header. The code can be compiled because there is version of shared_ptr ctor which takes as second parameter __dynamic_cast_tag. When you try to compile the code with C++11, you will get error because shared_ptr implementation is taken from memory header (where there is no ctor of shared_ptr which takes __dynamic_cast_tag as second parameter).
I have a class that has a container in it. This container must be a template and must accept std::vector. The code needs to be C++11 standard. I have simplified for this question, but it is equivalent to:
#include <vector>
template <template <typename, typename...> class Container>
class Test {
Container<double> c;
};
class TestImplementation : public Test<std::vector> {};
Recently I have found this fails to build for icpc16 as shown by CompilerExplorer https://godbolt.org/g/AGgojV with the error message:
too few arguments for template template parameter "Container"
Container<double> c;
It compiles for gcc, clang and icpc17. Is this a bug in icpc16 or is my code incorrect?
I'm integrating my app into Android AOSP source code to compile. I encountered an issue said as below:
ERROR: Dex writing phase: classes.dex has too many IDs. Try using multi-dex
It worked fine in android studio. My app setting looks like:
public class App extends MultiDexApplication{
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
Setting in mainifest.xml
android:name=".App"
dependencies{
compile 'com.android.support:multidex:1.0.1'
}
defaultConfig {
multiDexEnabled true
}
I found a solution at here:
How to enable mulit dex ,when building apk in AOSP?
but it didn't work.
My mk file looks like:
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := multidex-1.0.1:libs/multidex-1.0.1.aar
Any help? Thanks in advance.
Added below two lines into your mk files. It should work.
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
LOCAL_JACK_FLAGS += --multi-dex native
So, I have this code from the edge.js instructions:
using System;
using System.Threading.Tasks;
using EdgeJs;
class Program
{
public static async void Start()
{
var func = Edge.Func(#"
return function (data, callback) {
callback(null, 'Node.js welcomes ' + data);
}
");
Console.WriteLine(await func(".NET"));
}
static void Main(string[] args)
{
Task.Run((Action)Start).Wait();
}
}
And I have nuget working so that I have installed edge.js with nuget install edge.js -o ./packages
But I can't figure out how to compile it on my Mac OSX. I've tried:
mcs -pkg:./packages program.cs
mcs -lib:./packages/Edgejs.0.10.0 program.cs
and a bunch other combinations. I always get this error:
error CS0246: The type or namespace name `EdgeJs' could not be found. Are you missing an assembly reference?
I have not tried monoDevelop yet. I'm hoping to get it to work with the mono command line tools so I don't need monoDevelop.
You can use -r to reference the Edgejs assembly.
mcs -r:./packages/Edge.js.0.10.0/lib/Edgejs.dll program.cs