在C#中传递结构体给C++编写的 DLL

本文详细介绍了如何在C#中向C++编写的DLL传递结构体,包括单个结构体和嵌套结构体的情况,以及如何接收并保存数据。涉及StructLayout特性和DllImport属性的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


一、在C#中传递结构体给C++编写的 DLL

在C#中传递结构体给C++编写的 DLL,需要确保结构体在内存中的布局是相同的。以下是一个简单的示例来演示如何在 C# 和 C++ 之间传递结构体:

C#代码

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    public int intValue;
    public float floatValue;
}

class Program
{
    [DllImport("YourCppLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void ProcessStruct(ref MyStruct data);

    static void Main()
    {
        MyStruct myStruct = new MyStruct();
        myStruct.intValue = 10;
        myStruct.floatValue = 3.14f;

        ProcessStruct(ref myStruct);
    }
}

C++ 代码:

#include <iostream>

struct MyStruct
{
    int intValue;
    float floatValue;
};

extern "C" __declspec(dllexport) void ProcessStruct(MyStruct* data)
{
    std::cout << "Received Struct: " << std::endl;
    std::cout << "Int Value: " << data->intValue << std::endl;
    std::cout << "Float Value: " << data->floatValue << std::endl;
}

请确保在 C# 中使用 StructLayout 特性,并指定结构体的布局方式为 Sequential,以及在 C++ 中使用 extern “C” 来避免名称修饰。在 C# 中使用 DllImport 引入 C++ 编写的 DLL,并在方法声明中使用 ref 关键字将结构体传递给 C++ 函数。

二、如果c#中包含结构体嵌套

C#代码

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct InnerStruct
{
    public int var1;
    public float var2;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct OuterStruct
{
    public InnerStruct inner;
    public double var3;
}

class Program
{
    [DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void ProcessOuterStruct(OuterStruct outer);

    static void Main()
    {
        OuterStruct outerData = new OuterStruct
        {
            inner = new InnerStruct { var1 = 10, var2 = 20.5f },
            var3 = 30.5
        };

        ProcessOuterStruct(outerData);
    }
}

C++代码

#include <iostream>

typedef struct {
    int var1;
    float var2;
} InnerStruct;

typedef struct {
    InnerStruct inner;
    double var3;
} OuterStruct;

extern "C" {
    __declspec(dllexport) void ProcessOuterStruct(OuterStruct outer)
    {
        std::cout << "Received data in C++:" << std::endl;
        std::cout << "Inner: var1 = " << outer.inner.var1 << ", var2 = " << outer.inner.var2 << std::endl;
        std::cout << "var3 = " << outer.var3 << std::endl;
    }
}

三、如果需要将收到的数据保存下来

如果你需要将收到的数据保存在c++中,可以这样做:

// 全局变量用于保存接收到的数据
OuterStruct receivedData;

extern "C" {
    __declspec(dllexport) void ProcessOuterStruct(OuterStruct outer)
    {
        // 保存接收到的数据到全局变量
        receivedData = outer;
    }
    __declspec(dllexport) void PrintSavedData()
    {
        std::cout << "Saved data in C++:" << std::endl;
        std::cout << "Inner: var1 = " << receivedData.inner.var1 << ", var2 = " << receivedData.inner.var2 << std::endl;
        std::cout << "var3 = " << receivedData.var3 << std::endl;
    }

在以上代码中,我们在C++中定义一个结构体类型的全局变量用于保存接收到的数据,并在函数ProcessOuterStruct中将接收到的数据保存到全局变量,此外,我们还额外设置了一个PrintSavedData函数,用于打印保存了的数据。我们可以在c#中添加对这个函数的调用,代码如下:

class Program
{
    [DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void ProcessOuterStruct(OuterStruct outer);
    
	[DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
	public static extern void PrintSavedData(OuterStruct outer);

    static void Main()
    {
        ProcessOuterStruct(outerData);
        PrintSavedData(outerData);
    }
}

/注意这里的DllImport必须每个函数都要写一遍,即不能这样:

    [DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void ProcessOuterStruct(OuterStruct outer);
	public static extern void PrintSavedData(OuterStruct outer);

只能这样:

    [DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void ProcessOuterStruct(OuterStruct outer);
    
	[DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
	public static extern void PrintSavedData(OuterStruct outer);

该部分的完整代码如下:

C++代码

#include <iostream>

typedef struct {
    int var1;
    float var2;
} InnerStruct;

typedef struct {
    InnerStruct inner;
    double var3;
} OuterStruct;

// 全局变量用于保存接收到的数据
OuterStruct receivedData;


extern "C" {
    __declspec(dllexport) void ProcessOuterStruct(OuterStruct outer)
    {
        std::cout << "Received data in C++:" << std::endl;
        std::cout << "Inner: var1 = " << outer.inner.var1 << ", var2 = " << outer.inner.var2 << std::endl;
        std::cout << "var3 = " << outer.var3 << std::endl;

        // 保存接收到的数据到全局变量
        receivedData = outer;
    }

    __declspec(dllexport) void PrintSavedData()
    {
        std::cout << "Saved data in C++:" << std::endl;
        std::cout << "Inner: var1 = " << receivedData.inner.var1 << ", var2 = " << receivedData.inner.var2 << std::endl;
        std::cout << "var3 = " << receivedData.var3 << std::endl;
    }
}

C#代码

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct InnerStruct
{
    public int var1;
    public float var2;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct OuterStruct
{
    public InnerStruct inner;
    public double var3;
}

class Program
{
    [DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void ProcessOuterStruct(OuterStruct outer);
    
	[DllImport("YourCppDLLName.dll", CallingConvention = CallingConvention.Cdecl)]
	public static extern void PrintSavedData(OuterStruct outer);

    static void Main()
    {
        OuterStruct outerData = new OuterStruct
        {
            inner = new InnerStruct { var1 = 10, var2 = 20.5f },
            var3 = 30.5
        };

        ProcessOuterStruct(outerData);
        PrintSavedData(outerData);
    }
}


总结

通过上述代码,你可以在 C# 中将结构体传递给 C++ 编写的 DLL 并进行处理。希望这对你有帮助!如果有任何疑问,请随时提出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值