• P/Invoke各种总结(五、C#与C++结构体的交互)


    C#在和C++进行交互时,有时候会需要传递结构体。

    做一些总结,避免大家在用的时候踩坑。

    一般情况

    例如我们在C++里定义了一个struct_basic结构体

    1 struct struct_basic
    2 {
    3     WORD  value_1;
    4     LONG  value_2;
    5     DWORD value_3;
    6     UINT  value_4;
    7     BOOL  value_5;
    8 };

    这种情况在C#里调用,只需要注意数据类型对应就行了

    在C#里定义如下

    1  struct struct_basic
    2     {
    3         public ushort value_1;
    4         public int value_2;
    5         public uint value_3;
    6         public uint value_4;
    7         public bool value_5;
    8     }

    使用导出函数来测试一下

     1 extern "C" __declspec(dllexport) void get_basic(struct_basic basic);
     2 
     3 extern "C" __declspec(dllexport) void get_basic(struct_basic basic)
     4 {
     5     basic.value_1 = 1;
     6     basic.value_2 = 2;
     7     basic.value_3 = 3;
     8     basic.value_4 = 4;
     9     basic.value_5 = FALSE;
    10 }

    在C#中调用

            [DllImport("lib.dll")]
            public static extern void get_basic(ref struct_basic basic);
    
    
            static void Main(string[] args)
            {
                struct_basic basic = new struct_basic();
                get_basic(ref basic);
                Console.WriteLine($"{basic.value_1}  {basic.value_2}  {basic.value_3}  {basic.value_4}  {basic.value_5}");
            }

    输出结果如下:

    包含字符串的情况

    C++

    1 struct struct_advanced
    2 {
    3     WORD id;
    4     CHAR message[256];
    5 };

    这种需要使用MarshalAsAttribute特性来指示如何在托管代码与非托管代码之间封送数据。

    UnmanagedType.ByValTStr表示 结构中大小固定的字符串
    SizeConst可以指定字符数组的大小

    C#

    1     [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
    2     struct struct_advanced
    3     {
    4         public ushort id;
    5 
    6         [MarshalAs(UnmanagedType.ByValTStr,SizeConst =256)]
    7         public string message;
    8     };

    使用导出函数测试

    C++

    1 extern "C" __declspec(dllexport) void get_advanced(struct_advanced* advanced);
    2 
    3 extern "C" __declspec(dllexport) void get_advanced(struct_advanced* advanced)
    4 {
    5     advanced->id = 101;
    6     lstrcpyW(advanced->message, L"HelloWorld");
    7 }

    在C#中调用

     1  class Program
     2     {
     3         [DllImport("lib.dll")]
     4         public static extern void get_advanced(ref struct_advanced advanced);
     5 
     6         static void Main(string[] args)
     7         {
     8             struct_advanced advanced = new struct_advanced();
     9             get_advanced(ref advanced);
    10             Console.WriteLine($"{advanced.id}  {advanced.message}");
    11         }
    12     }

    输出结果:

    示例代码

  • 相关阅读:
    实现移动端1像素线--stylus
    用户信息认证session和token
    深入了解new的过程,和call,apply,bind的区别
    微信公众号开发过程--踏坑指南
    Better-scroll巨坑!!!
    JS ES6中Arguments和Parameters的区别
    知识点1
    面试--随笔1
    pytts3语音合成遇到的中文问题
    需求,需要谁参与进来?
  • 原文地址:https://www.cnblogs.com/zhaotianff/p/13300438.html
Copyright © 2020-2023  润新知