Here或完整版本的here,您可以找到Unity的示例GRPC“ Hello World”项目。只有为Unity构建并包装在DLL中的第一个版本才能在Unity IDE和独立构建上完美运行 fine 。 Raw Grpc.Core文件在IDE中正确引用了所有内容,但存在编组问题。
不幸的是,它无法使用IL2CPP后端为UWP构建。 Unity会生成项目并创建一个.sln项目。但是,Visual Studio总是在最终编译时为LRPC2001提供GRPC属性。
以下是第一个错误代码:
LNK2001 unresolved external _grpccsharp_init@0
LNK2001 unresolved external _grpccsharp_shutdonw@0
LNK2001 unresolved external _grpccsharp_version_string@0
...
好吧,感谢@Sunius,我对其进行了更多研究。有几点,我要补充一点:
在GRPC C#程序包中,有两种有关引用 extern 方法的方法。它们被命名为静态和共享库。
internal class DllImportsFromStaticLib
{
private const string ImportName = "__Internal";
[DllImport(ImportName)]
public static extern void grpcsharp_init();
[DllImport(ImportName)]
public static extern void grpcsharp_shutdown();
...
}
和
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();
...
}
我尝试使用共享的文件进行测试,但我得到了另一个链接错误文件,该文件有些不同。
LNK2001 unresolved external _dlopen@8
LNK2001 unresolved external _dlsym@8
...
在两种单独的方法中,外部方法已连接到内部接口:
public NativeMethods(DllImportsFromStaticLib unusedInstance)
{
this.grpccsharp_init = DllImportsFromStaticLib.grpccsharp_init;
this.grpccsharp_shutdown = DllImportsFromStaticLib.grpccsharp_shutdonw;
...
}
和
public NativeMethods(DllImportsFromSharedLib unusedInstance)
{
this.grpccsharp_init = DllImportsFromSharedLib.grpccsharp_init;
this.grpccsharp_shutdown = DllImportsFromSharedLib.grpccsharp_shutdonw;
...
}
此处定义了将调用的方法:
private static NativMethods LoadNativeMethodsUnity()
{
switch(PlatformApis.GetUnityRuntimePlatform())
{
case "IPhonePlayer":
return new NativeMethods(new NativeMethods.DllImportsFromStaticLib());
default:
return new NativeMethods(new NativeMethods.DllImportsFromSharedLib());
}
}
一些更新:
由于@jsmouret,his Grpc Github中有使用伪造方法的Stub.c文件,因此Linker不再抱怨Grpc_init方法。
下一个错误:dlopen,dlsym,dlerror:
首先,我尝试使用相同的Stub技术,但在这种情况下它无济于事,或者我做错了。
由于@Sunius,我注释掉了所有“ __内部” dll导入代码。因此,我没有遇到任何dlopen,dlsym和dlerror错误。
下一个错误:它发生在应用程序内部,而不是Visual Studio调试器。它告诉我:“ 例外:要封送托管方法,请在方法定义中添加一个名为'MonoPInvokeCallback'的属性。”
exception: error loading the embedded resource "Grpc.Core.roots.pem"
和
exception: To marshal a managed method, please add an attribute named 'MonoPInvokeCallback' to the method definition.
在我搜索完它之后,我知道了我的选择,但问题是,我应该针对哪种方法进行操作?!
答案 0 :(得分:2)
感谢我的同事Alice @Sunius和@jsmouret,最后,grpc通过以下步骤在Unity Platform上的UWP上工作:
现在,您应该会遇到_dlopen错误。
现在,您不再遇到构建错误,但需要使Grpc正常工作。
搜索类似“ DefaultSslRootsOverride”的内容,并注释如下:
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);
//}
}
}
}
搜索类似“ static void HandWrite”的内容,并在下面添加类似属性的内容:
[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);
}
}
我想,您完成了。万一它不适用于您的UWP,请告诉我,也许我可以帮忙。 :)
答案 1 :(得分:1)
您的插件似乎使用“ __Internal” P / Invoke来调用这些本机函数:
但是,链接器无法找到这些功能,因此会失败。您应该更改该代码以指定实现功能的DLL文件名,或者将带有这些功能定义的源文件拖放到Unity项目中。或者,如果实际上未调用该代码路径(因为您说过它可在独立播放器上使用),请从UWP构建中#ifdef。
您可以在此处找到有关“ __内部” P /调用的更多信息:
https://docs.unity3d.com/Manual/windowsstore-plugins-il2cpp.html