C++向C#传结构体

在写项目的时候,我需要将C++中接收到的结构体传输到我的C#项目中使用。结构体中基本是int,int[],float类型数据,这些类型在C++和C#中是一样的,可以直接传输,但是结构体怎么传输呢?下面是简单示例:

MyStruct.h

extern "C" {
#pragma pack(1)
	typedef struct _data1{  
		int id[4];  }Data1;
	typedef struct _data2{  
		int aa;}Data2;
	typedef struct _data3{  
	float cc;
	} Data3;
	typedef struct _data4{  
		int ee[4];  }Data4;
	typedef struct _data5{  
		int vv[3][3];  }Data5;
	typedef struct _data{
		Data1 d1;
		Data2 d2;
		Data3 d3;
		Data4 d4;
		Data5 d5;
	}MyStruct; 
	
#pragma pack()
}

MyStruct.cpp

这里可以看到,我返回一个结构体指针,因为无法直接传递一个结构体。

extern "C"{
__declspec(dllexport) MyStruct* GetStruct();
__declspec(dllexport) void FreeStruct(MyStruct* ptr);//一定不要忘了释放内存函数
}//目的是暴露函数接口,也可以在头文件中声明
MyStruct* GetStruct() {  
    // 分配并初始化一个MyStruct实例的内存  
    MyStruct* pStruct = new MyStruct(); 
    //对pStruct指向结构体进行处理,下面是示例
    pStruct->d1.id[0] = 123;  
    pStruct->d1.id[1] = 23;  
    pStruct->d1.id[3] = 22;  

    pStruct->d2.aa = 456;  
    pStruct->d3.cc = 123.123;  
    pStruct->d5.vv[0][0] = 11;
    pStruct->d5.vv[1][1] = 12; 
    pStruct->d5.vv[2][1] = 13; 
    return pStruct;  
    }
    
void FreeStruct(MyStruct* ptr) {  
    delete ptr;  	
}

Class1.cs

在C#中构造一个跟C++一样的结构体

class Class1
    {


        public struct data1
        {
            public int[] id;
        }
        public struct data2
        {
            public int aa;
        }
        public struct data3
        {
            public float cc;
        }
        public struct data4
        {
            public int[] ee;
        }
        public struct data5
        {
            public int[,] vv;
        }
        public struct MyStruct
        {
            public data1 d1;
            public data2 d2;
            public data3 d3;
            public data4 d4;
            public data5 d5;


        }
        public static MyStruct my = new MyStruct();
    }

Class2.cs

由于MyStruct是复杂的嵌套结构体,因此创建一个MyStruct1用于接收传过来数据,不能直接传到MyStruct,接收数据会不对。

using System.Runtime.InteropServices;

namespace testdemo
{
    class Class2
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct MyStruct1
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public int[] id;
            public int aa;
            public float uu;
            public int[] ee;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] // 3x3总共9个元素,多加2是因为我发现传过来数据往后移了两位  
            public int[] dd;
            // 提供一个属性来方便按二维索引访问  
        }
        public static MyStruct1 my1 = new MyStruct1();
    }
}

Ctrl.cs

using System;
using System.Runtime.InteropServices;
namespace testdemo
{
    class Ctrl
    {
    	[DllImport("MyStruct.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr GetStruct();
		[DllImport("MyStruct.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void FreeStruct(IntPtr ptr);
        IntPtr ptr = GetStruct();
        if(ptr != IntPtr.Zero) // 确保地址有效  
        {
        	Class2.my1 = (Class2.MyStruct1)Marshal.PtrToStructure(ptr, typeof(Class2.MyStruct1));
        	ExData();//写一个my1数据复制给my的函数
            FreeStruct(ptr);//释放内存!!一定不要忘记!!
        }
     }
}

总结:

  1. 结构体从C++到C#,用结构体指针。
  2. 嵌套的复杂结构体传输,要在C#这边构造两个结构体,一个用于接收数据,一个用于还原结构体。
  3. 传输结束后,记得释放指针指向内存。

注意

上述有个二维数组,因为其在最后,所以好像对后面数据没什么影响,但是在实际项目中,我发现数据复制过程中可能会因为[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] // 3x3总共9个元素,多加2是因为我发现传过来数据往后移了两位 public int[] dd; // 提供一个属性来方便按二维索引访问 出错,这里给大家提个醒,自己试验一下。

  • 12
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值