pInvoke、.net 4 与 3.5
我有一个关于从托管代码到非托管代码的 p/invoke 的问题。请参阅我在 MSDN 论坛上的原始帖子< /a> (如本文后面的简要总结所示)。在继续之前,我只想解释几件事:我在 net 3.5 中有一个包装器程序集,它对非托管代码进行实际的互操作。然后我有我的控制台“主机应用程序”,它使用包装程序集。
我提出的解决方案(我参考我的 MSDN 帖子)在主机应用程序使用 .net 4 时有效,但在将主机应用程序更改为使用 .net 3.5 时不起作用。更改时,我收到 AccessViolationException。
- 主机应用程序:4.0,包装程序集:3.5 ->作品
- 主机应用程序:3.5,包装程序集:3.5 ->投掷 AccessViolationException
有人知道我为什么会收到 AccessViolationException 吗?最重要的是,如何让它与 .net 3.5 一起工作?
我参考的 MSDN 帖子的简要摘要。我有这个混乱的 p/Invoke 我需要解决。 C 声明如下所示:
long TBAPI TbeAndring (short,
short,
PTB_PU,
PTB_ANDRING_INFO,
PTB_PARAMS,
PTB_PREMIE_NIVA_INFO,
PTB_PREMIE,
PTB_FORMAN_INFO,
PTB_FORMAN,
PTB_FUNK,
PTB_PARAMS,
PTB_PREMIE_NIVA_INFO,
PTB_PREMIE,
PTB_FORMAN_INFO,
PTB_FORMAN,
PTB_FUNK);
其中 PTB 表示每个参数都是指向任意长度数组的结构指针。结构体主要包含字符串、双精度数、字符型和短整型。不管怎样,我最终得到了这个 DllImport 语句:
<DllImport(NativeLibraryName, CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi, SetLastError:=True)>
Public Shared Function TbeAndring(ByVal sAntMoment As Short, _
ByVal sAntPU As Short, _
<[In]()> ByVal atbpu As PTB_PU(), _
<[In]()> ByVal atbandringinfo() As PTB_ANDRING_INFO, _
<[In]()> ByVal atbparamsEfter() As PTB_PARAMS, _
<[In]()> ByVal aNivaInfoEfter() As PTB_PREMIE_NIVA_INFO, _
<[In](), Out()> ByVal atbpremieEfter() As PTB_PREMIE, _
<[In]()> ByVal atbFormanInfoEfter() As PTB_FORMAN_INFO, _
<[In](), Out()> ByVal atbFormanEfter() As PTB_FORMAN, _
<[In](), Out()> ByVal atbfunkEfter() As PTB_FUNK, _
<[In]()> ByVal atbparamsFore() As PTB_PARAMS, _
<[In]()> ByVal aNivaInfoFore() As PTB_PREMIE_NIVA_INFO, _
<[In](), Out()> ByVal atbpremieFore() As PTB_PREMIE, _
<[In]()> ByVal atbFormanInfoFore() As PTB_FORMAN_INFO, _
<[In](), Out()> ByVal atbFormanFore() As PTB_FORMAN, _
<[In](), Out()> ByVal atbfunkFore() As PTB_FUNK) As Int32
End Function
正如您所看到的,一些参数也被非托管代码更改了。
I've an issue regarding p/invoke from managed to unmanaged code. See my original post at the MSDN forum (as brief summary is seen later in this post). Before I go on, I just want to explain a couple of things: I have a wrapper assembly in net 3.5 that does the actual interop to the unmanaged code. Then I have my console "host app" which uses the wrapper assembly.
The solution I came up (I refer to my MSDN post) works when the host app is using .net 4, but it doesn't work when changing the host app to use .net 3.5. When changing, I get a AccessViolationException.
- host app: 4.0, wrapper assembly: 3.5
-> works - host app: 3.5, wrapper assembly: 3.5 -> throws
AccessViolationException
Do anyone have a clue to why I get an AccessViolationException? Most importantly, how do I get it working with .net 3.5?
Brief summary on the MSDN post I refered to. I have this messy p/Invoke I need to solve. The C declaration looks like this:
long TBAPI TbeAndring (short,
short,
PTB_PU,
PTB_ANDRING_INFO,
PTB_PARAMS,
PTB_PREMIE_NIVA_INFO,
PTB_PREMIE,
PTB_FORMAN_INFO,
PTB_FORMAN,
PTB_FUNK,
PTB_PARAMS,
PTB_PREMIE_NIVA_INFO,
PTB_PREMIE,
PTB_FORMAN_INFO,
PTB_FORMAN,
PTB_FUNK);
Where PTB means that each argument is a struct pointer to an array of arbitrary length. The structs mostly contains strings, doubles, char and short. Anyway, I ended up with this DllImport statement:
<DllImport(NativeLibraryName, CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi, SetLastError:=True)>
Public Shared Function TbeAndring(ByVal sAntMoment As Short, _
ByVal sAntPU As Short, _
<[In]()> ByVal atbpu As PTB_PU(), _
<[In]()> ByVal atbandringinfo() As PTB_ANDRING_INFO, _
<[In]()> ByVal atbparamsEfter() As PTB_PARAMS, _
<[In]()> ByVal aNivaInfoEfter() As PTB_PREMIE_NIVA_INFO, _
<[In](), Out()> ByVal atbpremieEfter() As PTB_PREMIE, _
<[In]()> ByVal atbFormanInfoEfter() As PTB_FORMAN_INFO, _
<[In](), Out()> ByVal atbFormanEfter() As PTB_FORMAN, _
<[In](), Out()> ByVal atbfunkEfter() As PTB_FUNK, _
<[In]()> ByVal atbparamsFore() As PTB_PARAMS, _
<[In]()> ByVal aNivaInfoFore() As PTB_PREMIE_NIVA_INFO, _
<[In](), Out()> ByVal atbpremieFore() As PTB_PREMIE, _
<[In]()> ByVal atbFormanInfoFore() As PTB_FORMAN_INFO, _
<[In](), Out()> ByVal atbFormanFore() As PTB_FORMAN, _
<[In](), Out()> ByVal atbfunkFore() As PTB_FUNK) As Int32
End Function
As you see some of the arguments are changed by the unmanaged code as well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不知道这是否是 AccessViolationException 的唯一原因,但我发现该异常来自使用损坏的 C 运行时库堆运行的非托管代码。特别是,一些本来包含有效指针的内存实际上包含了垃圾:当取消引用时,它指向不存在的内存。
如果您遇到这样的问题,那么 .NET 版本的更改可能只是转移了该问题,使得该问题已在 .NET 3.5 下出现,但尚未在 .NET 下出现4.0。
我建议在调试器下运行代码,并包括本机代码调试。你可能会发现原来的异常。
I don't know if it's the only reason for AccessViolationException, but I've seen that exception come from unmanaged code that was running with a corrupt C runtime library heap. In particular, some memory which was meant to contain a valid pointer came to contain garbage: when dereferenced, it pointed to nonexistant memory.
If you have an issue like this, then the change in .NET version may simply have moved the problem around, such that the problem has been seen under .NET 3.5 but has not yet been seen under .NET 4.0.
I recommend running the code under the debugger, and including Native code debugging. You may find the original exception.