从VB.net调用DLL会导致堆异常

时间:2018-09-25 02:51:00

标签: c string windows vb.net dll

我用gcc制作了一个仅包含以下功能的DLL:

#include <windows.h>

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

,它基于this answer末尾的代码。构建命令为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参数“返回”字符串,但这似乎在客户端上进行了大量工作,我会希望对客户来说尽可能地简化它,即看看我是否可以使这种方法起作用。

1 个答案:

答案 0 :(得分:2)

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

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

但是,由于存在多种表示字符串的方式,因此返回类型为String的信息尚不明确。使用MarshalAs属性可以告诉运行时如何处理返回的值:

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

详细了解Interop MarshalingPassing strings between managed and unmanaged code