UE(虛幻)學習(三) UnrealSharp插件中調用非托管DLL

上一篇文章中我使用UnrealSharp成功使用了我的一個C#控制臺程序中的網絡模塊,這個程序是基于KCP網絡了,其中調用了Cmake 編譯的一個C++的DLL,在虛幻中DLL需要放在Binaries目錄中才可以。Unity中只要放在任意Plugins目錄中就可以。
但是Binaries目錄版本控制一般不提交,我們可以改一下,改成按照路徑加載。

修改前的腳本

using System.Runtime.InteropServices;//腳本修改自//https://github.com/a11s/kcp_warppernamespace 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.pswp.cn/web/64505.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64505.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64505.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

編譯openssl遇到錯誤Parse errors: No plan found in TAP output的解決方法

在編譯openssl時 tar -zxvf openssl-1.1.1p.tar.gz cd openssl-1.1.1p ./config --prefix/usr --openssldir/etc/ssl --shared zlib make make test 遇到錯誤 Parse errors: No plan found in TAP output 解決方法&#xff1a; yum install perl-Test-Simple

IO多路復用(select/epoll)

目錄 一、概念 二、語法 1.select 1.1 select函數的語法 1.2 文件描述符集合操作 1.3 select函數的優缺點 2.epoll 2.1 epoll語法 2.2 epoll的工作模式 2.3 epoll的優缺點 三、select服務端代碼 四、epoll服務端代碼 五、客戶端代碼 一、概念 IO多路復用是一種同…

android stdudio環境: gradle一直安裝失敗

一、一直顯示如下錯誤 The specified Gradle distribution file:/home/wangqingyuan/.gradle/wrapper/dists/gradle-8.6-bin/gradle-8.6-bin.zip does not exist. 經分析&#xff0c;是因為應用本身設置了gradle版本的地址為本地&#xff1a; 應用目錄&#xff1a;gradle/gra…

解決PS 撤銷卡頓

1. 關閉Windows Ink - 打開觸控筆設置 - 禁用Windows Ink功能 2. 創建 PSUserConfig.txt&#xff08;注意Win10/11 可能隱藏文件擴展名&#xff09; - 位置&#xff1a;C:\Users\[用戶名]\AppData\Roaming\Adobe\Adobe Photoshop CC 2019\Adobe Photoshop CC 2019 Se…

spring默認線程池SimpleAsyncTaskExecutor特點為什么要盡量避免使用

在 Spring Boot 中&#xff0c;默認的線程池配置由 TaskExecutionAutoConfiguration 類提供&#xff0c;使用的是 SimpleAsyncTaskExecutor。 SimpleAsyncTaskExecutor特點 每次調用創建新線程&#xff1a; SimpleAsyncTaskExecutor 每次執行任務時都會創建一個新線程&#xf…

軟件測試 Linux 服務器監控命令的基本知識

Linux 服務器因其高效、穩定、開源等優勢&#xff0c;廣泛用于網絡服務、數據庫管理、應用開發等領域。而為了確保服務器的正常運行和性能&#xff0c;我們必須不斷監控服務器的狀態。這就需要我們熟悉一些基本的監控命令。 本文將詳細介紹多種監控命令的使用方法及其應用。同…

Spring 的不同事務傳播行為

目錄 Spring 的不同事務傳播行為 PROPAGATION_REQUIRES_NEW事務傳播行為什么情況下會使用? 一、PROPAGATION_REQUIRES_NEW的含義 二、使用場景 三、注意事項 PROPAGATION_NESTED事務傳播行為什么情況下會使用? 一、PROPAGATION_NESTED的含義 二、使用場景 三、嵌套事…

【Linux】進度條

本文中&#xff0c;我們來寫一個進度條。 本文大綱&#xff1a; 寫一個命令行版的進度條。 1.回車換行 2.緩沖區問題&#xff08;本文不深究&#xff09; ? 2.1測試代碼 3.寫一個什么樣的進度條&#xff1f; ? version1 ? version2 回車換行 這倆不是一個概念&…

SLAM/數字圖象處理基礎

概念 視差&#xff1a;相同特征的不同深度估計的偏差 BoW&#xff0c;DBoW&#xff0c;DBoW2的區別是什么 Bag of Words (BoW)、DBoW&#xff08;Dynamic Bag of Words&#xff09;和DBoW2是用于圖像處理和計算機視覺中的不同特征表示和匹配方法。它們之間的主要區別如下&am…

UE5材質節點SimpleGrassWind

SimpleGrassWind節點可以模擬樹葉擾動&#xff0c;或小草晃動效果 用來做風格化樹、風格化草效果很好 主要節點 前三個節點分別用來控制&#xff0c;風強度&#xff0c;風重力&#xff0c;風速度&#xff0c;WPO是世界位置偏移

WeNet:面向生產的流式和非流式端到端語音識別工具包

這篇文章介紹了WeNet&#xff0c;一個面向生產的開源端到端&#xff08;E2E&#xff09;語音識別工具包。WeNet的主要特點和貢獻如下&#xff1a; 統一流式和非流式識別&#xff1a;提出了一種名為U2的兩階段框架&#xff0c;能夠在單一模型中同時支持流式和非流式語音識別&…

Ubuntu20.04安裝Foxit Reader 福昕閱讀器

Ubuntu20.04安裝Foxit Reader 福昕閱讀器 文章目錄 Ubuntu20.04安裝Foxit Reader 福昕閱讀器 先更新一下源 sudo apt update sudo apt upgrade下載Foxit Reader的穩定版本 wget https://cdn01.foxitsoftware.com/pub/foxit/reader/desktop/linux/2.x/2.4/en_us/FoxitReader.e…

2024年底關于期貨的工作總結

十幾年程序猿出身&#xff0c;因幾年前的懵懂無畏闖入期貨市場&#xff0c;盈了&#xff0c;感覺期貨太簡單&#xff0c;飄然裸辭&#xff0c;想當財務自由者&#xff0c;全職做交易。當深入學習時&#xff0c;卻虧了&#xff0c;原來市場是讓人敬畏的&#xff0c;也是反人性的…

c++入門——c++輸入cin和輸出cout的簡單使用

c輸入cin、輸出cout 1 cin2 cout3 cin和cout說明 c在c語言的輸入、輸出函數的基礎上進行了封裝。 1 cin c可以理解為控制臺&#xff0c;in可以理解為輸入。 參考代碼&#xff1a; void f(){int a;float b;double c;char d;cin>>a>>b>>c>>d;//這里和…

PlantUML 時序圖 基本例子

基本的例子 序列-> 用于繪制兩個參與者之間的信息。參與者不必明確聲明。 要有一個點狀的箭頭&#xff0c;就用--> 也可以用<- 和<-- 。這不會改變繪圖&#xff0c;但可能提高可讀性。注意&#xff0c;這只適用于順序圖&#xff0c;其他圖的規則不同。 plantum…

YOLOv10-1.1部分代碼閱讀筆記-utils.py

utils.py ultralytics\nn\modules\utils.py 目錄 utils.py 1.所需的庫和模塊 2.def _get_clones(module, n): 3.def bias_init_with_prob(prior_prob0.01): 4.def linear_init(module): 5.def inverse_sigmoid(x, eps1e-5): 6.def multi_scale_deformable_attn_py…

vue3使用video-player實現視頻播放(可拖動視頻窗口、調整大小)

1.安裝video-player npm install video.js videojs-player/vue --save在main.js中配置全局引入 // 導入視頻播放組件 import VueVideoPlayer from videojs-player/vue import video.js/dist/video-js.cssconst app createApp(App) // 視頻播放組件 app.use(VueVideoPlayer)2…

基于卷積神經網絡的甲狀腺結節識別系統,resnet50,mobilenet模型【pytorch框架+python源碼】

更多目標檢測、圖像分類識別、目標追蹤等項目可看我主頁其他文章 功能演示&#xff1a; 甲狀腺結節識別系統&#xff0c;卷積神經網絡&#xff0c;resnet50&#xff0c;mobilenet【pytorch框架&#xff0c;python源碼】_嗶哩嗶哩_bilibili &#xff08;一&#xff09;簡介 …

C++--類與對象

1.封裝 封裝是c面向對象的三大特性之一 將屬性和行為作為一個整體 將屬性和行為加以權限控制 語法&#xff1a; class 類名{ 訪問權限: 屬性/行為 }; 訪問權限 public 公共權限 類內類外均可以訪問 protected 保護權限 類內可以訪問&#xff0c;類外不可以訪問 pr…

區塊鏈期末復習3:跨鏈原子交換其他加密貨幣

參考教材&#xff1a;《區塊鏈&#xff1a;技術驅動金融》 一、跨鏈原子交換&#xff08;不可分割的交叉鏈互換&#xff09; 1.實施步驟 假設Alice要拿1BTC交換Bob的3BCY。Alice作為交易的發起者。 1&#xff09;Alice創建一個secret&#xff08;一個隨機數x), 并計算其哈希…