C语言 从 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).

这表示堆损坏。 我做错了什么?


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

  • 更改为__stdcall并使用Declare Auto Function testfunc Lib "testfunc.dll" Alias "testfunc@0" () As String而不是<DllImport...>声明函数

正常工作的操作:

  • 更改函数以返回整数;但是我当然无法访问我的字符串。

注意:我知道我可以尝试通过ByRef StringBuilder参数"返回"字符串,正如我链接的线程上建议的那样,但这在客户端似乎有很多工作,我想让它尽可能简单对于客户端,即看看我是否可以让这种方法工作。

为了在托管代码和非托管代码之间传递数据,必须正确地混搭数据。由于运行时无法知道您的testfunc()返回什么,因此您必须通过提供它的声明来告诉它,您通过以下方式完成

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

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

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

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

相关内容

最新更新