javascript - Unity C# 如何正确加载托管 DLL?

标签 javascript c# unity3d dll

基于来自这里的另一个问题 Using OpenH264 DLL in C# Project我基本上是在尝试使用图书馆 https://github.com/secile/OpenH264Lib.NET统一实时编码 H264 视频文件,使用统一的 JINT 原生库用于 JavaScript 互译
不过,我在统一引用 DLL 时遇到了很多困难。
我按照来自 GitHub 站点的说明进行编译,并设法编译为 OPenH264Lib.dll(以及示例项目,并让示例项目在 windows x64 上与 Visual Studio 2019 一起工作,并且它对所有内容进行编码等),但是当我干脆拖拽编译好的OpenH264Lib.dll到 Unity 项目的 Assets 文件夹中的 Plugins 文件夹,我无法访问命名空间 OpenH264Lib ,它在那里的标准 C# 示例中用于访问 DLL 托管函数,它只是在统一控制台中说找不到命名空间。
好的,所以我决定用 Visual Studio 构建一个 C# DLL,它本身加载在 OpenH264Lib.dll 中,然后从那里调用它的函数,然后统一使用 C# DLL,所以这是我在visuaal studio 中的 C# 代码(在放置了在 Debug 文件夹中编译(使用 .NET 版本 4.6.1)OpenH264Lib.dll,就像在示例中一样,并且我在 Visual Studio 2019 中没有收到任何引用错误):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sayfir
{
    public class Class1
    {
        public static OpenH264Lib.Encoder ok(string path)
        {
            var code = new OpenH264Lib.Encoder(path);
            return code;
        }
    }
}
好的,所以这完美构建,没有错误,它似乎与示例文件夹(在 Assets /插件中)一样。
然后,当我获取在我的解决方案的 x64/Debug 文件夹中生成的 DLL 文件(OpenH264Lib.dll 和 Sayfir.dll)并将它们复制到 Unity 中的 Plugins 文件夹时,然后尝试像这样统一访问它
public class Yetzirah {
        public static void Wellz() {
            var k = Sayfir.Class1.ok("2");
            Debug.Log(k);
        }
}
我在 Unity 控制台中收到错误消息Assets\scripts\Yetzirah.cs(45,12): error CS0012: The type 'Encoder' is defined in an assembly that is not referenced. You must add a reference to assembly 'OpenH264Lib, Version=1.0.7598.38705, Culture=neutral, PublicKeyToken=null'.所以它似乎可以识别从上面的源代码编译的 Sayfir.dll 文件,但不能识别它所依赖的 OpenH264Lib.dll,即使两者都在同一个文件夹中(在 Assets/Plugins 中)
我听说过 .rsp 文件,但我尝试制作一个名为 csc.rsp 的文件。并将其添加到带有内容的 Assets 中-r:OpenH264Lib依然没有
我也听说过 .asmdef文件但是当我用内容制作一个
{
    "references":  "OpenH264Lib" 
}
但仍然什么都没有,我对 asmdef 文件不太了解,我也不太了解这个错误,或者一般来说如何统一使用托管 C++ DLL。
我也看过an article that mentions referencing external DLL files in unity ,但它说去Project > Edit References > .NET Assembly问题是,我不知道如何在 UnityEditor 2020 中到达那个屏幕,或者是否有办法到达那里或完成同样的事情,如果是这样,我不知道如何也无法找到它在寻找
我尝试使用标准 dllexports 制作另一个 DLL,头文件内容为
extern "C" __declspec(dllexport) int well();
然后在 .cpp 文件中
#include "deeall.h"
__declspec(dllexport) int well() {
    return 634;
}
然后在统一 C#
DllImport("deeall.dll", EntryPoint="well")]
public static extern int well();
然后它可以工作,但是当我在 dll extern int 中包含任何类型的托管库时,我收到错误 __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention.如果我想对 C# 包装器使用 __declspec 导出,这是必要的
作为一个黑客,我尝试将以下内容添加到 Encoder.cpp 文件本身(来自 OpenH264Lib .dll 的源代码)
    __declspec(dllexport) int well() {
        String ^h = "ok";
        Encoder
        ^enc = 
        gcnew Encoder(
            h
        );
        return 4;
    }
尝试直接调用 Encoder 函数,(以及对 Encoder.h 的以下头文件修改:
namespace OpenH264Lib {
    extern "C" __declspec(dllexport) int well();
    //etc.. rest of code in namespace.....
)
然后团结起来
[DllImport("OpenH264Lib6.dll", EntryPoint="well")]
public static extern int well();
但是当我调用 well() , unity 挂了一段时间然后崩溃了,没有任何错误
那么我怎样才能让 OpenH264Lib.dll 统一工作,或者其他类似的托管编译 C++ DLL 统一工作?如果这是不可能的,有没有其他方法可以在 Unity 中使用 OpenH264?如果没有,是否还有其他解决方案可以实时统一编码 H264 视频(来自 byte[]s)?

最佳答案

这是从内存中编写的,未经测试,但我认为它会起作用。

  • 确保正确加载 OpenH264Lib.dll,否则手动加载,例如在您的包装器中使用 Assembly.Load/Assembly.LoadFrom
  • 确保 openh264-1.7.0-win32.dll 位于可执行文件旁边或指定完整路径
  • 确保不要混合使用 32Bit 和 64Bit
  • 像您一样构建您的 Sayfir 包装程序集,但不要公开 Encoder 类本身,而是包装您要使用的方法。这样 Unity 就不需要知道关于 OpenH264Lib.dll 的任何信息

  • 例如
    
    public class Wrapper 
    {
      private Encoder _encoder;
      public Wrapper() 
      {
        // Be sure the openh264-1.7.0-win32.dll can be found! 
        // Native dlls should be located next to the actual executable if you call it without a full path!
        _encoder = new OpenH264Lib.Encoder("openh264-1.7.0-win32.dll");
      }
    
      public void Setup(/* ... */)
      {
        //_encoder.Setup(...)
      }
    }
    
    
    如果它仍然不起作用,请在尝试加载 OpenH264Lib.dll 之前尝试使用此方法重定向 DLL 查找路径。在编码器类的源代码中,我们看到对 LoadLibrary 的调用,它将使用您在此处提供的路径来搜索 DLL。加载后通过 null 再次调用该函数恢复正常搜索顺序作为论据。
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetDllDirectory(string lpPathName);
    
    https://www.pinvoke.net/default.aspx/kernel32.LoadLibrary

    关于javascript - Unity C# 如何正确加载托管 DLL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64347537/

    相关文章:

    c# - 在 OData 查询中使用复杂类型

    c# - 为什么未加载ScriptableObject Assets 中的嵌套资源引用?

    javascript - 在指令中使用 templateUrl 会卡住应用程序

    javascript - 使用可重复查找元素数组时 Protractor 测试出现问题

    javascript - 非常简单的 AngularJS $http POST 结果为 '400 (Bad Request)' 和 'Invalid HTTP status code 400'

    c# - 如何通过FindWindow api调用C#开发的window

    javascript - 如何调用函数,如果 bool 值在 Angular2 中为真?

    javascript - 关注第一个asp :textbox in each bootstrap tab when clicking tab link

    unity3d - 如何将 Input.GetAxis ("Mouse X") 或 Input.GetAxis ("Mouse Y") 转换为新的输入系统?

    c# - 统一注册表单验证