从 C++ dll 中导出方法,需要从 C# 中使用它。 C++ 方法具有复杂的嵌套结构和联合作为参数。我无法将字符串数据从 C# 发送到 C++。
C++以下,pdll_sensor_test结构体有name变量。无法将值从 C# 发送到 C++。它打印为空。
Source.cpp (C++)
#include "pch.h"
#include <stdio.h>
extern "C"
{
enum pdll_test_id
{
dut_com_init = 0,
cont_pkt_tx = 1,
};
struct pdll_sensor_test
{
pdll_test_id test_id;
bool en;
char name[13];
int reg_addr;
};
union pdll_test_data
{
pdll_test_id id;
pdll_sensor_test sensor;
};
struct pdll_device
{
bool is_active;
pdll_test_data test;
};
__declspec(dllexport) int PdllDeviceMethod(pdll_device* pdlldevice)
{
printf("pdlldevice->is_active=%d\n", pdlldevice->is_active);
printf("pdlldevice->test.sensor.test_id=%d\n", pdlldevice->test.sensor.test_id);
printf("pdlldevice->test.sensor.en=%d\n", pdlldevice->test.sensor.en);
printf("pdlldevice->test.sensor.name=%s\n", pdlldevice->test.sensor.name);
printf("pdlldevice->test.sensor.reg_addr=%d\n", pdlldevice->test.sensor.reg_addr);
return 0;
}
}
Program.cs (C#)
using System;
using System.Runtime.InteropServices;
namespace CSharpApp
{
public class Program
{
public enum pdll_test_id
{
dut_com_init = 0,
cont_pkt_tx = 1,
};
[StructLayout(LayoutKind.Sequential)]
public struct pdll_sensor_test
{
public pdll_test_id test_id;
public bool en;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
public string name;
public int reg_addr;
};
//This is union in C++
[StructLayout(LayoutKind.Explicit)]
public struct pdll_test_data
{
[FieldOffset(0)]
public pdll_test_id id;
[FieldOffset(4)]
public pdll_sensor_test sensor;
};
[StructLayout(LayoutKind.Sequential)]
public struct pdll_device
{
public bool is_active;
public pdll_test_data test;
};
[DllImport("CPPDynamicDLL.dll")]
public static extern int PdllDeviceMethod(ref pdll_device pdlldevice);
public static void Main(string[] args)
{
Console.WriteLine("This is C# program");
pdll_device pdllDevice = new pdll_device();
pdllDevice.is_active = true;
pdllDevice.test.id = pdll_test_id.dut_com_init;
pdllDevice.test.sensor.test_id = pdll_test_id.cont_pkt_tx;
pdllDevice.test.sensor.en = true;
pdllDevice.test.sensor.name = "wsa";
pdllDevice.test.sensor.reg_addr = 1024;
var result = PdllDeviceMethod(ref pdllDevice);
}
}
}
我尝试使用封送处理,但无法将变量名从 C# 发送到 C++。
根据https://learn.microsoft.com/en-us/dotnet/framework/interop/marshalling-classes-structures-and-unions#unions-sample,值类型和引用类型(例如字符串)不允许重叠。提供的示例使用 C# 结构的两个变体来模拟 C++ 联合。我认为你可以尝试类似的方法:
C#
public enum pdll_test_id : Int32
{
dut_com_init = 0,
cont_pkt_tx = 1,
};
[StructLayout( LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi )]
public struct pdll_sensor_test
{
public pdll_test_id test_id;
[MarshalAs( UnmanagedType.I1 )]
public bool en;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 13 )]
public string name;
public int reg_addr;
};
[StructLayout( LayoutKind.Sequential, Pack = 4)]
public struct pdll_test_data_1
{
public pdll_test_id id;
};
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
public struct pdll_test_data_2
{
public pdll_sensor_test sensor;
};
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
public struct pdll_device_1
{
[MarshalAs( UnmanagedType.I1 )]
public bool is_active;
public pdll_test_data_1 test;
};
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
public struct pdll_device_2
{
[MarshalAs( UnmanagedType.I1 )]
public bool is_active;
public pdll_test_data_2 test;
};
[DllImport( @"CPPDynamicDLL.dll", CallingConvention = CallingConvention.Cdecl )]
public static extern int PdllDeviceMethod( ref pdll_device_1 pdlldevice );
[DllImport( @"CPPDynamicDLL.dll", CallingConvention = CallingConvention.Cdecl )]
public static extern int PdllDeviceMethod( ref pdll_device_2 pdlldevice );
pdll_device_2 pdllDevice = new pdll_device_2( );
pdllDevice.is_active = true;
pdllDevice.test.sensor.test_id = pdll_test_id.cont_pkt_tx;
pdllDevice.test.sensor.en = true;
pdllDevice.test.sensor.name = "wsa";
pdllDevice.test.sensor.reg_addr = 1024;
var result = PdllDeviceMethod( ref pdllDevice );
该示例还使用了一些额外的声明(可能是多余的)来确保 C# 在本实验中与 C++ 正确通信。您也可以使用原始的未更改的 C++ 代码,只调整 C# 声明。
也可以考虑固定数组,如固定字节名称 [13] 和指针,但这需要激活不安全代码选项。或者您可以将数据构造为字节数组并将其传递给 DLL。
或者可以在 C++/CLI 中创建一个可以更轻松地与 C# 和 C 交互的中间类库。
因此,如果可以重建DLL,最好避免union。