如何创建适配C DLL调用的VB.NET非托管结构体(含结构体数组)
在VB.NET中正确定义并调用含结构体数组的C DLL函数
我来帮你搞定这个跨语言调用的结构体问题!你已经正确定义了Inner结构体,接下来重点是把Outer结构体的定义补全,同时保证内存布局和C语言完全匹配,这样才能顺利调用DLL函数。
完整的VB.NET结构体定义
<StructLayout(LayoutKind.Sequential)> Public Structure Inner Public x As Integer Public y As Integer End Structure <StructLayout(LayoutKind.Sequential)> Public Structure Outer ' 用MarshalAs标注固定大小数组,SizeConst对应C里的数组长度20 <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> Public ArrayOfInners() As Inner ' C的unsigned char直接对应VB.NET的Byte类型 Public b As Byte End Structure
导入DLL中的目标函数
假设你的C DLL里的函数原型是这样的:
void ProcessOuter(Outer* pOuter);
那在VB.NET里可以这样声明导入:
<DllImport("你的DLL文件名.dll", CallingConvention:=CallingConvention.Cdecl)> Public Shared Sub ProcessOuter(ByRef outer As Outer) End Sub
提示:如果你的DLL用的是
stdcall调用约定(比如Windows系统API常用的),把CallingConvention.Cdecl改成CallingConvention.StdCall就行。
实际调用示例
现在你可以创建Outer实例、填充数据,然后调用DLL函数了:
' 初始化Outer实例 Dim myOuter As Outer ' 固定大小数组需要先初始化元素(索引0到19,共20个) ReDim myOuter.ArrayOfInners(19) ' 给数组里的元素赋值 myOuter.ArrayOfInners(0).x = 100 myOuter.ArrayOfInners(0).y = 200 For i As Integer = 1 To 19 myOuter.ArrayOfInners(i).x = i * 10 myOuter.ArrayOfInners(i).y = i * 20 Next ' 设置b字段的值 myOuter.b = 1 ' 调用DLL里的函数 ProcessOuter(myOuter)
关键注意事项
- 必须保留
StructLayout(LayoutKind.Sequential),这能保证VB.NET结构体的内存顺序和C语言完全一致,避免封送时出现内存错位。 - 固定大小数组一定要用
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)>标注,不然CLR没法正确识别数组长度,大概率会触发内存访问错误。 - 数据类型要严格对应:C的
int对应VB.NET的Integer,unsigned char对应Byte,绝对不能混用。
内容的提问来源于stack exchange,提问作者Lambtron
相关产品推荐
相关产品推荐

