亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將復雜的數據結構從 C# 傳遞到本機 dll

將復雜的數據結構從 C# 傳遞到本機 dll

C#
HUWWW 2022-07-23 17:59:12
我正在從 NetCore 應用程序調用用 C 編寫的第三方庫。問題是,為了使用這個庫,我首先需要進行調用并配置一個復雜的結構,該結構稍后必須傳遞給所有后續調用。void createCtx(modbus_t ** ctx){    *ctx = modbus_new_tcp("192.168.1.175", 502);    //configure the context here ....    int res = modbus_connect(*ctx);}int pollData(modbus_t * ctx){    //....    modbus_read_bits(ctx, addr, 1, tab_rp_bits);    //....}我的方法是在調用者應用程序 (C#) 上創建 modbus_t 對象,通過調用 createCtx 對其進行配置,然后定期將其傳遞給 pollData。我已經閱讀了有關 StructLayout 的內容,但由于我不需要訪問 modbusContext 對象中的數據,我只想為上下文保留一塊內存,讓 C# 忘記里面的內容。這就是我想出的static IntPtr modbusContext;static class ModbusDriver{            [DllImport("modbusdriver",EntryPoint = "createCtx")]            public static extern void CreateCtx(ref IntPtr modbusContext);            [DllImport("modbusdriver",EntryPoint = "pollData")]            public static extern uint PollData(IntPtr modbusContext)        }        static void Main(string[] args)        {            int ctxSize = ModbusDriver.GetCtxSize();            modbusContext = Marshal.AllocHGlobal(80 * Marshal.SizeOf(typeof(byte))); //<--- 80 is the result of sizeof(modbus_t)            ModbusDriver.CreateCtx(ref modbusContext);            while(true)            {                ModbusDriver.PollData(modbusContext);                Thread.Sleep(1000);            }        }    }這一切似乎都行得通,但感覺不太對勁,尤其是因為 modbus_t 結構相當復雜struct modbus_t {    /* Slave address */    int slave;    /* Socket or file descriptor */    int s;    int debug;    int error_recovery;    struct timeval response_timeout;    struct timeval byte_timeout;    struct timeval indication_timeout;    const modbus_backend_t *backend;    void *backend_data;};所以我的問題是,我的方法正確嗎?具體來說, modbus_t 包含指針。我設法在 C# 中保留了 modbus_t 結構,它似乎可以工作,但是假設結構中包含的指針引用的內存在調用之間不會被破壞真的安全嗎?感覺不對。
查看完整描述

1 回答

?
元芳怎么了

TA貢獻1798條經驗 獲得超7個贊

只要您不想修改數據,就可以安全地將數據包裝為 void * 或 IntPtr。您通過 AllocHGlobal 分配數據,后者通過 LocalAlloc 從本地進程堆返回數據,最終調用 RtlAllocateHeap。對于 C#,該指針是一個黑盒子,永遠不會寫入或修改它。只要您不提前釋放數據,一切都會好起來的。

C 編程規則適用:您需要手動管理內存,并注意誰擁有數據以及誰負責刪除它。

只有當您嘗試將該指針映射到部分嘗試授予對某些字段的訪問權限的托管類時,才會出現問題。然后您需要注意結構成員對齊方式與 C 頭文件中的對齊方式相同,并且您需要為要跳過的數據獲取正確的偏移量。然后,您可以將 IntPtr 轉換為 C# 結構,作為帶有不安全代碼的指針,如果您得到正確的偏移量和對齊,它應該可以工作。

如果 C++ 類是包含 STL 數據類型的頭文件的一部分,情況就完全不同了。這些東西根本不是可包裝的,因為成員對齊取決于您當前編譯器的隨附 STL 版本,這在私有成員字段之間強加了一個緊密的合同,可以在 C++/STL 版本之間更改。為此,您需要一個 C 包裝器,它將輔助方法包裝為普通的 C 方法,具有內部調用 C++ 方法的常用結構。托管 C++ 是一種相當過時的技術,不應再使用。

總結一下:您目前的方法很好,并且會奏效。如果您想從字節 blob 訪問修改數據,這將變得更加工作,但是一旦您知道如何在 C# 中聲明僅包含原始類型(沒有字符串、字典或指向托管堆結構的指針)的包裝器結構,這也是可行的。


查看完整回答
反對 回復 2022-07-23
  • 1 回答
  • 0 關注
  • 189 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號