【问题标题】:How to use a C++ dll in Unity3D?如何在 Unity3D 中使用 C++ dll?
【发布时间】:2013-04-10 10:42:31
【问题描述】:

我知道this similar question,但它没有回应我的问题。

我使用 Visual Studio 2010 编写了两个 .dlls。一个是 C++,并与用 C++ 编写的 SDK 通信。另一个是该 C++ 库的 C# 包装器,因此可以在 C# 上下文中使用。

我的计划是让我在Unity3D 中使用我的代码,但显然情况并非如此。如果.NET 不是.NET 程序集,似乎Unity3D 不允许我将.dlls 作为资产导入。所以我可以添加我的 C# 包装器,但不能添加 C++ dll。

每当我尝试访问 C++ 库时,这都会导致DllNotFoundException。我尝试简单地将 C++ 库复制到 Assets/Plugins 文件夹中,但结果相同。

有没有办法正确地做到这一点?这是我的项目设置中非常重要的部分。

【问题讨论】:

  • 如何调用 C++ DLL?您不需要将其作为参考添加到您的解决方案中。它是本机资源。
  • @SimonWhitehead 我使用PInvoke 调用C++ 函数,使用[DllImport("Foo.dll")]。当两个 dll 在同一个文件夹中时它可以工作,但我不知道 Unity 如何处理 dll 插件。
  • 您使用的是什么许可证?你的目标是什么?

标签: c# c++ dll unity3d


【解决方案1】:

问题是p/invoke运行时代码调用LoadLibrary(YourNativeDllName)时找不到DLL。

您可以通过确保您的 DLL 位于 DLL 搜索路径中的第一次 p/invoke 调用来解决此问题。例如通过调用SetDllDirectory

我个人更喜欢的解决方案是让您的托管代码 p/调用对 LoadLibrary 的调用,将完整的绝对路径传递给本机 DLL。这样,当后续 p/invoke 诱导调用 LoadLibrary(YourNativeDllName) 时,您的本地 DLL 已经在进程中,因此将被使用。

internal static class NativeMethods
{
    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
    internal static extern IntPtr LoadLibrary(
        string lpFileName
    );
}

然后在你的代码中的某个地方:

private static IntPtr lib;

....

public static void LoadNativeDll(string FileName)
{
    if (lib != IntPtr.Zero)
    {
        return;
    }

    lib = NativeMethods.LoadLibrary(FileName);
    if (lib == IntPtr.Zero)
    {
        throw new Win32Exception();
    }
}

只需确保调用 LoadNativeDll 并将完整路径传递给本机库,然后再调用该本机库的任何 p/invokes。

【讨论】:

  • 我真的必须为此使用库的绝对路径吗?我不是唯一一个从事这个项目的人,所以这会使事情变得非常复杂......
  • 嗯,是的。但这并不意味着您必须对路径进行硬编码。您可以在运行时构建它。将本机 DLL 和托管 DLL 放在同一文件夹中,并以此方式构建路径。您的 p/invoke 声明仍然只使用 DLL 名称,即"mydll.dll"。但是,系统必须以某种方式找到您的 DLL,这一事实无可避免。您不能只是将 DLL 放在您喜欢的任何地方,并希望系统会为您找到它。
  • 我知道我不能随便把它放在任何地方;我希望 Unity3D 能让我以某种方式将其指定为依赖项,以便以类似于访问 C# 的方式访问它。当你说我可以在运行时建立路径时,你建议我怎么做?将我的 dll 作为插件导入后,Unity3D 会移动它,所以我不知道该怎么做。
  • 原生 DLL 不同。您不能以相同的方式将它们添加为参考。您必须对 DLL 搜索路径之类的东西感到沮丧和肮脏。我对 Unity 插件方面一无所知。我确实知道答案中的方法有效,只要您可以确定您的 DLL 所在的位置。
  • 那么,在使用该代码之后,我仍然像往常一样使用 PInvoke 吗?或者我会改变我现有的代码以某种方式使用lib 指针?
【解决方案2】:

请注意,DllNotFoundException 可能是由在 Debug 而非 Release 中构建 Unity DLL 引起的!

一个简单的疏忽可能会导致头痛。

【讨论】:

  • 所以没有办法在编辑器中运行它来测试你每次都必须编译发布的东西?
  • 据我所知,这是正确的。在 Unity 中运行 DLL 时,您无法检测 DLL。我已经通过制作 C++ 测试单元来解决这个问题,但是是的,就是这样。
【解决方案3】:

当 Unity 可以找到您的 DLL,但无法找到它的依赖项时,也会发生这种情况。明显的解决方法是将依赖 DLL 也放入 /Plugins 中,或者静态链接您的依赖。

不太明显的原因是当您的 DLL 动态依赖于 Visual Studio 运行时库时,是使用属性 -> C/C++ -> 代码生成 -> /MD 选项构建的。将其更改为 /MT 以静态链接运行时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多