UE(虚幻)学习(三) UnrealSharp插件中调用非托管DLL

news2025/1/4 5:24:16

上一篇文章中我使用UnrealSharp成功使用了我的一个C#控制台程序中的网络模块,这个程序是基于KCP网络了,其中调用了Cmake 编译的一个C++的DLL,在虚幻中DLL需要放在Binaries目录中才可以。Unity中只要放在任意Plugins目录中就可以。
但是Binaries目录版本控制一般不提交,我们可以改一下,改成按照路径加载。

修改前的脚本

using System.Runtime.InteropServices;

//脚本修改自//https://github.com/a11s/kcp_warpper

namespace NetLibrary
{
    
    public unsafe class KCP
    {


        const string LIBNAME = "libikcp.dll";
        //---------------------------------------------------------------------
        // interface
        //---------------------------------------------------------------------

        /// <summary>
        /// create a new kcp control object, 'conv' must equal in two endpoint
        /// from the same connection. 'user' will be passed to the output callback
        /// output callback can be setup like this: 'kcp->output = my_udp_output'
        /// </summary>
        /// <param name="conv"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        [DllImport(LIBNAME, EntryPoint = "ikcp_create", CallingConvention = CallingConvention.Cdecl)]
        public static extern IKCPCB* ikcp_create(uint conv, void* user);

        /// <summary>
        /// release kcp control object
        /// </summary>
        /// <param name="kcp"></param>
        [DllImport(LIBNAME, EntryPoint = "ikcp_release", CallingConvention = CallingConvention.Cdecl)]
        public static extern void ikcp_release(IKCPCB* kcp);

        /// <summary>
        /// set output callback, which will be invoked by kcp
        ///public static extern void ikcp_setoutput(IKCPCB* kcp, int (* output)(byte* buf, int len,             ikcpcb *kcp, void* user));
        /// </summary>
        /// <param name="kcp"></param>
        /// <param name="d_output"></param>
        [DllImport(LIBNAME, EntryPoint = "ikcp_setoutput", CallingConvention = CallingConvention.Cdecl)]
        public static extern void ikcp_setoutput(IKCPCB* kcp, System.IntPtr d_output);

       

篇幅太大没有必要,只展示部分代码片段。
可以看到之前是通过DllImport 载入LIBNAME变量来载入DLL的。

改为动态路径

先放上所有改动

// 动态获取库路径
private static string GetLibraryPath()
{
    string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
    //动态库的路径被拼接到 Binaries\Managed\Third\libikcp.dll,而你的实际库文件存放在 E:\myproject\Third\libikcp.dll,这说明 AppDomain.CurrentDomain.BaseDirectory 返回的路径是 Binaries\Managed。
    baseDirectory = Path.Combine(baseDirectory, "../../");
    string relativePath;
    
    // 根据平台选择库路径
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        relativePath = "ThirdParty/Kcp/Win64/libikcp.dll";
    }
    else if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("ANDROID")))
    {
        relativePath = "ThirdParty/Kcp/Android/arm64-v8a/libikcp.so";
    }
    else
    {
        throw new PlatformNotSupportedException("Unsupported platform");
    }

    return Path.Combine(baseDirectory, relativePath);
}

// DllImport 使用动态路径
private const string LIBNAME = "PLACEHOLDER"; // 占位符
private static bool _isResolverSet = false;
// 添加初始化方法以动态设置路径
public static void Initialize()
{
    if (_isResolverSet)
    {
        Loger.Debug($"BSserver DLL: 已经加载过了 .");
        return;
    }
    try
    {
        string libraryPath = GetLibraryPath();
        
        //Loger.Error($"BSserver DLL:{libraryPath}");
        NativeLibrary.SetDllImportResolver(typeof(KCP).Assembly, (name, assembly, path) =>
        {
            if (name == LIBNAME)
            {
                return NativeLibrary.Load(libraryPath);
            }
            return IntPtr.Zero;
        });
        _isResolverSet = true;
    }
    catch(Exception e) {
        //AClientMain.inst.PrintString("C# : DLL:" + libraryPath);
        Console.WriteLine($"Loaded library 加载错误 ."+e.Message);
        Loger.Error($"BSserver DLL 加载错误 : " + e.Message);
    }
    
}
//const string LIBNAME = "libikcp.dll";
//---------------------------------------------------------------------
// interface
//---------------------------------------------------------------------

/// <summary>
/// create a new kcp control object, 'conv' must equal in two endpoint
/// from the same connection. 'user' will be passed to the output callback
/// output callback can be setup like this: 'kcp->output = my_udp_output'
/// </summary>
/// <param name="conv"></param>
/// <param name="user"></param>
/// <returns></returns>
[DllImport(LIBNAME, EntryPoint = "ikcp_create", CallingConvention = CallingConvention.Cdecl)]
public static extern IKCPCB* ikcp_create(uint conv, void* user);

/// <summary>
/// release kcp control object
/// </summary>
/// <param name="kcp"></param>
[DllImport(LIBNAME, EntryPoint = "ikcp_release", CallingConvention = CallingConvention.Cdecl)]
public static extern void ikcp_release(IKCPCB* kcp);

使用方法:
我们在UE的工程下创建目录ThirdParty,按照代码里的路径,把DLL放进去,按照不同平台。

在加载DLL之前,我们需要调用Initialize方法初始化动态设置路径就可以了。

这些代码是ChatGPT帮忙写的,经过几次修改有了这段代码。

小技巧

以前是内事不决问baidu,外事不决问google,现在是内事问豆包,外事问ChatGPT。 :)
但是小心AI一本正经的胡说八道。 :P

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【循环神经网络】RNN介绍

在人工神经网络中&#xff0c;”浅层网络”是指具有一个输入层、一个输出层和最多一个没有循环连接的隐藏层的网络。随着层数的增加&#xff0c;网络的复杂性也在增加。更多的层或循环连接通常会增加网络的深度&#xff0c;并使其能够提供不同级别的数据表示和特征提取&#xf…

【论文投稿】Python 网络爬虫:探秘网页数据抓取的奇妙世界

【IEEE出版|广东工业大学主办】第五届神经网络、信息与通信工程国际学术会议&#xff08;NNICE 2025&#xff09;_艾思科蓝_学术一站式服务平台 目录 前言 一、Python—— 网络爬虫的绝佳拍档 二、网络爬虫基础&#xff1a;揭开神秘面纱 &#xff08;一&#xff09;工作原…

基于深度学习的视觉检测小项目(二) 环境和框架搭建

一、环境和框架要求 SAM的环境要求&#xff1a; Python>3.7 PyTorch>1.7 torchvision>0.8 YOLO V8的环境要求&#xff1a;YOLO集成在ultralytics库中&#xff0c;ultralytics库的环境要求&#xff1a; Python>3.7 PyTorch>1.10.0 1、确定pytorch版本…

SQLiteDataBase数据库

XML界面设计 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:layout_width"match_paren…

cesium小知识: 处理动画的5种方式

在 Cesium 中处理动画可以通过多种方式实现,具体取决于你想要创建的动画类型。Cesium 提供了丰富的API来支持不同种类的动画,包括但不限于物体的移动、旋转、缩放、属性变化等。以下是几种常见的动画处理方法: 1. 使用 Entity 和 SampledProperty 对于动态数据或随时间变化…

【鸿蒙NEXT】鸿蒙里面类似iOS的Keychain——关键资产(@ohos.security.asset)实现设备唯一标识

前言 在iOS开发中Keychain 是一个非常安全的存储系统&#xff0c;用于保存敏感信息&#xff0c;如密码、证书、密钥等。与 NSUserDefaults 或文件系统不同&#xff0c;Keychain 提供了更高的安全性&#xff0c;因为它对数据进行了加密&#xff0c;并且只有经过授权的应用程序才…

visual studio连接sql server数据库

目录 1、为什么要建立连接2、在sql server中建立数据库3、visual studio连接sql server数据库4、学生信息管理系统页面布局5、添加事件逻辑 5.1 页面跳转5.2 读取学生信息5.3 查询学生信息5.4 修改学生信息5.5 删除学生信息5.6 添加学生信息 bilibili演示视频 github源码 1、…

STM32-笔记23-超声波传感器HC-SR04

一、简介 HC-SR04 工作参数&#xff1a; • 探测距离&#xff1a;2~600cm • 探测精度&#xff1a;0.1cm1% • 感应角度&#xff1a;<15 • 输出方式&#xff1a;GPIO • 工作电压&#xff1a;DC 3~5.5V • 工作电流&#xff1a;5.3mA • 工作温度&#xff1a;-40~85℃ 怎么…

vuex - 第一天

思维逻辑 解决问题 代码能力2 vue2的项目 北京前端鸿蒙6期 语雀 vuex 在组件中使用 插件支持v2和v3 宏任务 和 微任务 多问问自己为什么 new的四步 查找数组里是否包含某个元素 同步任务、异步任务、微任务、宏任务

三大行业案例:AI大模型+Agent实践全景

本文将从AI Agent和大模型的发展背景切入&#xff0c;结合51Talk、哈啰出行以及B站三个各具特色的行业案例&#xff0c;带你一窥事件驱动架构、RAG技术、人机协作流程&#xff0c;以及一整套行之有效的实操方法。具体包含内容有&#xff1a;51Talk如何让智能客服“主动进攻”&a…

STM32G0B1 can Error_Handler 解决方法

问题现象 MCU上电&#xff0c;发送0x13帧数据固定进入 Error_Handler 硬件介绍 MCU :STM32G0B1 can:NSI1042 tx 接TX RX 接RX 折腾了一下午&#xff0c;无解&#xff0c;问题依旧&#xff1b; 对比测试 STM32G431 手头有块G431 官方评估版CAN 模块&#xff1b; 同样的…

【服务器】上传文件到服务器并训练深度学习模型下载服务器文件到本地

前言&#xff1a;本文教程为&#xff0c;上传文件到服务器并训练深度学习模型&#xff0c;与下载服务器文件到本地。演示指令输入&#xff0c;完整的上传文件到服务器&#xff0c;并训练模型过程&#xff1b;并演示完整的下载服务器文件到本地的过程。 本文使用的服务器为云服…

基于微博热搜评论的情感分析与热点主题挖掘研究

目录 1、绪论 1.1 研究背景与研究意义 1.2 数据来源 1.3 技术路线 2、数据预处理 2.1 数据清洗与准备 2.2 导入必要库与加载数据 2.3 加载停用词表与分词处理 2.4 统计词频与高频词分析 3、情感分析与主题建模 3.1 情感分析 3.2 主题建模 3.3 热点主题识别 4、数据可视…

“进制转换”公式大集合

咱们都知道十进制是“逢10进1 ”&#xff0c;同理&#xff0c;N进制就是 “逢N进1”。进制其实就这么简单。它的麻烦之处在于各种进制之间的转换。 一、十进制整数转N进制 1&#xff0e;十进制转二进制 除2取余法&#xff1a;连续除以2&#xff0c;直到商为0&#xff0c;逆序…

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…

echarts 柱形图重叠柱形图legend,双y轴

echarts 图表组件&#xff1a; <template><div :style"{ height: 100% }"><div class"foldLine" ref"foldLine" :style"{ width: widths, height: heights }"></div></div> </template> <scr…

MySQL5.7主从同步配置

环境&#xff1a; 使用2台虚拟机&#xff0c;如图-1所示。其中192.168.4.51是主服务器,另一台192.168.4.52作为从服务器&#xff0c;通过调取主服务器上的binlog日志&#xff0c;在本地重做对应的库、表&#xff0c;实现与主服务器的数据同步。 主服务器、从服务器都已安装好m…

方正畅享全媒体新闻采编系统 imageProxy.do 任意文件读取漏洞复现

0x01 产品简介 方正畅享全媒体新闻生产系统是以内容资产为核心的智能化融合媒体业务平台,融合了报、网、端、微、自媒体分发平台等全渠道内容。该平台由协调指挥调度、数据资源聚合、融合生产、全渠道发布、智能传播分析、融合考核等多个平台组成,贯穿新闻生产策、采、编、发…

Ubuntu安装Apache Airflow详细指南

本文我们介绍如何在Ubuntu上安装Apache Airflow。Apache Airflow旨在通过编程方式编写、调度和监控工作流。随着数据编排在现代数据工程中变得越来越重要&#xff0c;掌握Apache Airflow等工具可以显著提高您的生产力和效率。 学习Apache Airflow的首要任务是安装单机版本进行测…

生物信息学软件开发综述学习

目录 ①编程语言和开源工具和库 ②轻量级 R 包开发 ③大规模组学软件开发 ④示例 1.轻量级 R 包开发示例及数据 2.大规模组学软件开发 文献&#xff1a;Bioinformatics software development: Principles and future directions ①编程语言和开源工具和库 在生物信息学…