获取访问违规异常将固定长度的字符串从 C# 传递到 dll 时
本文关键字:字符串 dll 访问 异常 获取 | 更新日期: 2023-09-27 18:36:54
我有以下(VB6?)代码在VBA for Excel中完美运行。 我正在使用的dll(x.dll)对我来说是一个"黑匣子"。 我不知道它是用什么写的,它是否是非托管的。 从历史技术的角度来看,我对它知之甚少。 我只知道这个特定的函数在从 Excel VBA 调用时有效,当我从 C# 调用它时,我无法同样让它发挥作用,我想我应该能够。 同样,c.b128 的值由 dll 使用和更改。
'In VBA for excel the value inside "c.b128" is changed from
'" 1234567890123456789012345678901234567890123456789012345678901234567890123456789 "
'to
'" 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 123456789 "
VBA for Excel Code
Private Type k128
b128 As String * 128
End Type
Private Declare Function dllSpace Lib "x.dll" (aInfo As Long, _
bVec As Long, cQry As k128, dErr As k128) As Long
Function Space() As Long
Dim c As k128
Dim d As k128
c.b128 = Left(" 1234567890123456789012345678901234567890123456789012345678901234567890123456789", 128)
d.b128 = Left("", 128)
Space = dllSpace(-1, -1, c, d)
End Function
我尝试在 .NET 中实现相同的内容,当它到达"返回 dllSpace(-1, -1, c, d);"时出现错误;在 [] 试图读取或写入受保护的内存时发生了 system.accessviarationexception 类型的未处理异常。 其他内存已损坏
我需要将其转换为.NET,并且我得到一个AccessViolationException。 我到处都读到StringBuilders保留的内存可以被C#中的dll访问。 我尝试过"ref StringBuilder",我尝试使用byte[],我尝试使用不安全的描述符,我不明白。 另外,如果有一种方法可以让我使用 IDE 查看内存中正在发生的事情,这对我也有帮助。 我可以在局部和监视窗口中看到我的所有变量,但我看不到也不知道如何查看有关抛出的异常的更多详细信息。 我在Win7 32位操作系统机器上使用Visual Studio Express 2013 for Windows Desktop。
这是我的 c# 代码中的一个片段
C# 代码片段
[DllImport(@"x.dll")]
private static extern int dllSpace(int aInfo,
int bVec,
StringBuilder cQry,
StringBuilder dErr);
public int StartTheDataSpace()
{
StringBuilder c = new StringBuilder(128);
StringBuilder d = new StringBuilder(128);
c.Append(" 1234567890123456789012345678901234567890123456789012345678901234567890123456789 ");
return dllSpace(-1, -1, c, d);
}
VBA代码清楚地表明,您拥有的实际上是一个包含固定长度字符串的结构。这意味着StringBuilder
是错误的类型。您应该改用:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct k128
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string b128;
}
另外,据我了解,VBA默认使用ByRef
。因此,C# 声明应该是:
[DllImport(@"x.dll")]
private static extern int dllSpace(
ref int aInfo,
ref int bVec,
ref k128 cQry,
ref k128 dErr
);
现在,碰巧ref k128
在编组时具有与容量为 128 的StringBuilder
相同的内存布局,因此您可能会发现切换回
[DllImport(@"x.dll")]
private static extern int dllSpace(
ref int aInfo,
ref int bVec,
StringBuilder cQry,
StringBuilder dErr
);