从 ac# 应用程序调用非托管 Dll 时,我得到一个AccessViolationException
. 奇怪的是导出的函数没有参数,所以问题不在于数据的编组。该函数没有参数,只返回一个整数。另请注意,调用约定不是问题。具有相同零参数和整数返回值(但名称不同)的相同函数可以正常工作。考虑到编组和调用约定被排除的事实,这样的调用可能导致此异常的其余候选原因是什么?
更新: dll 函数是正确的,因为如果通过普通链接从其他非托管代码调用,那么它可以完美运行。
更新 2:一切都在 32 位上编译和运行。我试过 Win XP SP2 和 Vista。这是一个有趣的事实:在 Vista 系统上,它就像一个魅力。在 XP 上它失败了。
更新 3:我没有得到源代码,但我了解了这个 dll 的本质,所以我尝试用我自己的 dll 重现问题。故事是这样的:原始 dll 是 ei.lib(Erlang 的 c 接口库)的某种包装器。它导出一些辅助函数。因此,为了重现该问题,我在 ei.lib 周围制作了一个包装 dll,它只导出一个函数,即“test()”。我这样做是为了不会弄乱编组和其他东西。我只想测试初始化、连接和发送消息。所以我的 dll 的这个 test() 函数只是调用ei_connect_init()
,然后ei_connect()
最后ei_reg_send()
,里面有硬编码的参数。问题是,如果我调用这个 dll 并使用另一个非托管代码中的 test() 函数,它可以正常工作。消息已发送。但是当我通过 DllImport 从 c# 调用它时,它只能在 Vista 上运行。不在XP上。在 XP 上,它在 .net 层上出现 AccessViolationException 失败。我试图追查问题,我从我的 dll 中看到,在 XP 上运行并被托管代码调用时,对 的任何调用ei_connect()
或任何读取尝试(这些在 ei.lib 中定义)都会导致尝试读取erl_errno
或写入受保护的内存,使应用程序崩溃。它不能是微不足道的,因为它可以在 Vista 上工作,并且在被非托管代码调用时也可以工作。