首页 > 解决方案 > 从 VB.net 调用 DLL 导致堆异常

问题描述

我用 gcc 制作了一个 DLL,它只包含以下函数:

#include <windows.h>

BSTR __declspec(dllexport) testfunc(void)
{
     return SysAllocString(L"Hello");
}

这是基于此答案末尾的代码。构建命令是gcc -shared -o testfunc.dll main.c -Os -s -loleaut32.

在使用 VS 2017 社区的 Visual Basic 中,我的代码是:

Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic
Imports System
Imports System.Text

Module Module1
    <DllImport("testfunc.dll", CallingConvention:=CallingConvention.Cdecl
               )>
    Private Function testfunc() As String
    End Function

    Sub Main()
    Dim Ret = testfunc()
    Console.WriteLine(Ret)
    End Sub
End Module

但是,执行程序会在从testfunc. 执行永远不会到达这Console.WriteLine条线。例外是:

The program '[15188] ConsoleApp1.exe' has exited with code -1073740940 (0xc0000374).

这表明堆损坏。我究竟做错了什么?


我尝试过的事情没有帮助:

正确工作的事情:

注意:我知道我可以尝试ByRef StringBuilder按照我链接的线程上的建议通过参数“返回”字符串,但这在客户端似乎需要做很多工作,我想让它尽可能简单对于客户,即看看我是否能让这种方法发挥作用。

标签: cstringwindowsvb.netdll

解决方案


为了在托管代码和非托管代码之间传递数据,必须对其进行适当的编组。由于运行时无法知道您的testfunc()返回值,您必须通过提供它的声明来告诉它,您通过

<DllImport("testfunc.dll")>
Private Function testfunc() As String

但是返回类型是 a 的信息String是模棱两可的,因为有多种字符串表示方式。使用MarshalAs -Attribute 告诉运行时如何处理返回值:

<DllImport("testfunc.dll")>
Private Function testfunc() As <MarshalAs(UnmanagedType.BStr)> String

阅读有关托管和非托管代码之间的互操作封送处理和传递字符串的更多信息。


推荐阅读