C#调用CLR动态库,传递结构体经验总结

C# 调用C C++动态库封装结构体,结构体数组

一、	结构体传递

typedef stuct
{
Int osVersion;
Char szVersion[128];
}OSINFO;

//1.获取版本信息(传递结构体指针)
extern “C”_declspec(dllexport) void _stdcall GetVsersionPtr(OSINFO *info);

//2.获取版本信息(传递结构体引用)
extern “C”_declspec(dllexport) void _stdcall GetVsersionRef(OSINFO &info);

可以通过两种方式进行调用

C#
[StructLayout(LayoutKind.Sequential)]
Public struct OSINFO
{
Public int osVersion
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=128)]
Public string szVersion;
}

1.方式一(传入结构体引用),在C#中结构体是以传值的方式传递,类才是以传地址的方式传递,加关键字ref即可。C端传递了两种不同的类型参数,都可以通过引用解决。
[DllImport("EfficiencyCLRWrapper.dll")]
static extern void GetVsersionPtr(ref OSINFO info);

2.方式二(传入IntPtr(平台通用指针))
intPtr pv=Marshal.AllocHGlobal(132);//结构体在使用时一定要分配空间(1*size(int)+128)
Marshal.Writnint32(pv,132);//想内存块中写入数值
If(GetVersionPtr(pv))//直接以非托管内存块地址为参数
{
Console.WriteLine(“osVersion:{0}”,Marshal.ReadInt32(pv,0));
Console.WriteLine(“szVersion:{0}”,Marshal.PtrToStringAnsi((IntPtr)(pv.ToInt32())+4);//移动4个字节
}
Marshal.FreeHGlobal(pv);//处理完记得释放内存


二、	结构体数组传递
C++中方法声明:

public void GetPlanes(plane *planes, int size);

 

C#中结构体声明:

[StructLayout(LayoutKind.Sequential)]
public struct GPlane
{
  public double timestamp;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  public float[] normal;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  public float[] center;
}

C#中方法声明:

[DllImport(LibFileName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern bool Pvr_getAirGlassPlanes([In, Out]GPlane[] plane, int size);

 

C#中调用该方法:

int size = 2;

GPlane[] plane = new GPlane[size];

Pvr_getAirGlassPlanes(plane, size);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C#调用 C 动态库时,结构体需保持字节对齐,否则可能会导致错误的结果。本文将介绍字节对齐的概念,以及如何在 C# 中保持结构体的字节对齐。 1. 字节对齐的概念 在计算机中,内存是按字节进行分配和管理的。当我们定义一个结构体时,它的成员变量会按照定义的顺序依次存储在内存中。由于不同的处理器架构对于数据的读取方式不同,因此在存储数据时需要考虑字节对齐的问题。 字节对齐是指在内存中分配空间时,保证结构体的成员变量按照一定的规则进行排列。例如,如果一个结构体中包含一个 4 字节的整型和一个 2 字节的字符型,那么在进行字节对齐时,会在整型后面添加 2 个空字节,以保证字符型的地址是 4 的倍数。这样做可以提高内存读取的效率,避免因为数据对齐不合理而导致的性能问题。 2. 在 C# 中保持结构体的字节对齐 在 C# 中,我们可以使用 StructLayout 特性来控制结构体的字节对齐方式。默认情况下,C# 中的结构体会按照 CLR 的规则进行字节对齐,这可能与 C 的规则不同。如果我们需要与 C 动态库进行交互,则需要使用 StructLayout 特性来指定字节对齐方式。 例如,如果我们有一个 C 语言中的结构体定义如下: ``` struct MyStruct { int intValue; char charValue; }; ``` 在 C# 中,我们需要使用 StructLayout 特性来指定字节对齐方式,如下所示: ``` [StructLayout(LayoutKind.Sequential, Pack = 1)] struct MyStruct { public int intValue; public char charValue; } ``` 在上面的代码中,我们使用 StructLayout 特性指定了结构体的字节对齐方式为 Sequential,即按照结构体成员的定义顺序进行排列,并且使用 Pack 属性指定了每个成员变量占用的字节数。在这个例子中,我们指定了 Pack = 1,表示每个成员变量都只占用一个字节。这样,在与 C 动态库进行交互时,就可以保证结构体的字节对齐方式与 C 语言中的规则相同。 需要注意的是,使用 StructLayout 特性可能会影响代码的可移植性和性能。如果不是必须与 C 动态库进行交互,建议不要使用 StructLayout 特性来指定字节对齐方式。 总结 在 C#调用 C 动态库时,结构体需保持字节对齐,否则可能会导致错误的结果。我们可以使用 StructLayout 特性来指定结构体的字节对齐方式,以保证与 C 语言中的规则相同。然而,使用 StructLayout 特性可能会影响代码的可移植性和性能,需要在实际开发中进行权衡。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值