簡體   English   中英

C# / C++ Interop:如何修改 class in C++ memory from C#

[英]C# / C++ Interop: How to modify class in C++ memory from C#

我在我的 C++ 項目中包含一個 C# DLL,我希望兩者都能夠輕松編輯相同的結構或 memory 中的 class 我可以使用函數來設置/獲取成員或結構,但我認為這會有很多更多的開銷和麻煩。 我寧願能夠直接編輯成員變量,將 C# 端的 memory 映射到匹配 C++ 端。

我正在使用 Mono 來管理來自 C++ 的 C#,但我不確定這是否重要。

這是我這樣做的嘗試,但 C# 中的任何更改只會影響 C# 結構。 我怎樣才能解決這個問題?

C++(非托管)代碼:

#ifdef ENGINE_CORE
    #define ENGINE_CORE_API __declspec(dllexport)
#else
    #define ENGINE_CORE_API __declspec(dllimport)
#endif

struct TestStruct {
    int myElement = 4;
};

TestStruct testStruct;

extern "C" {
    ENGINE_CORE_API void GetTestStruct(TestStruct** transf) {
        *transf = &testStruct;
    }
}

C#(托管)代碼:

[StructLayout(LayoutKind.Sequential)]
class TestStruct {
    public int myElement;
};

public class Example {
    // Called in a loop:
    public void OnUpdate() {
        GetTestStruct(out TestStruct testStruct);
        testStruct.myElement += 2;
        Logger.Print($"Int: {testStruct.myElement}");
    }

    #region DllImports
    [DllImport("EngineCore")]
    static extern void GetTestStruct([Out] out TestStruct comp);
    #endregion
}

Output:

[2022-02-26 00:02:54.959] [Debug Logger] [info] Int: 6
[2022-02-26 00:02:55.220] [Debug Logger] [info] Int: 6
[2022-02-26 00:02:55.234] [Debug Logger] [info] Int: 6

預計 Output:

[2022-02-26 00:02:54.959] [Debug Logger] [info] Int: 6
[2022-02-26 00:02:55.220] [Debug Logger] [info] Int: 8
[2022-02-26 00:02:55.234] [Debug Logger] [info] Int: 10

從 C# 端,您可以將 object 實例的所有字段的所有相對 memory 地址偏移量帶入 C++ 並使用添加到其 object 地址的偏移量訪問它們並轉換為它們的 POD 類型。

那么您的 C++ class 將僅由直接指向 C# object 字段的指針組成。

struct TestStruct {

    // points to relevant field
    int* myElement;
};

TestStruct t({ptr_from_csharp});
*t.myElement=5; // pinned C# object's field changes

如果您需要相反的東西,那么 C++ 端不需要額外的固定操作,因為它沒有 GC。

如果你不想擺弄指針類型字段,那么你可以在 C# 上重載字段的 getter/setter 並在這些 getter/setter 方法中運行 C++ DLL 這樣它看起來像 C# 從外部擁有 memory 但實際上只改變C++ 空間 memory。

class TestStruct {
    public int myElement {
        get { return cpp("C++");} 
        set { cpp("change C++");}
    }
};

但這會帶來互操作開銷。

我會編寫某種 awk 或 perl 腳本來讀取 C# class 並吐出所需的 C++ 結構。

為此,這將有助於:

  • 使用腳本識別並用於標識所述類的注釋來注釋或括起 C# 類

  • 將 C++ 結構移動到單獨的 header 文件

然后,當 C# class 更改時,只需在相關文件上運行腳本並重新編譯您的 C++ 代碼。

不要忘記讓腳本寫出注釋 output 文件是機器生成的效果,這樣您就不會無意中手動編輯它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM