【问题标题】:How do I import and call unmanaged C dll with ANSI C string "char *" pointer string from VB.NET?如何从 VB.NET 导入和调用带有 ANSI C 字符串“char *”指针字符串的非托管 C dll?
【发布时间】:2013-07-14 00:00:54
【问题描述】:

我已经编写了自己的函数,在 C 中会这样声明,使用标准的Win32 调用约定:

int Thing( char * command, char * buffer, int * BufSize);

我已经弄清楚了以下数量的 Visual Basic 代码,它们应该导入 DLL 文件并调用此函数,将其包装起来以便于调用 Thing("CommandHere",GetDataBackHere)。

更新:此代码现在是一个有效的解决方案,如下所示:

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

Namespace dllInvocationSpace

    Public Class dllInvoker

        ' I tried attributes, but I could not make it build:
        ' <DllImport("thing1.dll", False, CallingConvention.Cdecl, CharSet.Ansi, "Thing", True, True, False, True)>
        Declare Ansi Function Thing Lib "thing1.dll" (ByVal Command As String, ByRef Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer

        ' This part contributed by helpful user:
        Shared Function dllCall(ByVal Command As String, ByRef Results As String) As Integer
            Dim Buffer As StringBuilder = New StringBuilder(65536)
            Dim Length As Integer = Buffer.Capacity
            Dim retCode As Integer = Thing(Command, Buffer, Length)
            Results = Buffer.ToString()
            'Debug.Assert(Results.Length = Length)  ' This assertion is not true for me
            Return retCode
        End Function

    End Class

End Namespace

我按照这里收到的帮助获得了要构建的代码,然后我忘记了As Return Type(它给了我一个 MarshalDirectiveException PInvokeRestriction)。然后我的 DLL 中出现了断言失败,这导致了 SEHException。一旦修复,这将非常有效。谢谢各位。有些新闻组里有人说这不能做,Visual Basic 只加载托管的 DLL 程序集(我猜这是大多数 Visual Basic 用户习惯的正常做法)。

【问题讨论】:

    标签: vb.net dll unmanaged dllimport


    【解决方案1】:

    这取决于您如何在 C 代码中使用缓冲区参数。如果您只将字符串 VB.NET 代码 传递到 您的 C 代码,那么将其声明为 ByVal String 就足够了。但是,如果您让 C 代码在缓冲区中返回一个字符串,那么您必须在调用之前将其声明为 ByVal StringBuilder 并正确初始化它。例如:

    Public Class dllInvoker
        Declare Ansi Function Thing Lib "Thing1.dll" (ByVal Command As String, ByVal Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer
    
        Shared Function dllCall(ByVal Command As String, ByRef Results As String) As Integer
            Dim Buffer As StringBuilder = New StringBuilder(65536)
            Dim Length As Integer = Buffer.Capacity
            Dim retCode As Integer = Thing(Command, Buffer, Length)
            Results = Buffer.ToString()
            Debug.Assert(Results.Length = Length)
            Return retCode
        End Function
    End Class
    

    注意返回的 Length 值中的歧义。

    【讨论】:

    • 有趣。尽管我确定您发送的代码比我的更正确,但我仍然收到 MarshalDirectiveException。 Thing1.dll 不是实际的 DLL 名称,但我担心的一件事是,如果我输入“foo3290809.dll”(不存在),我会得到相同的 MarshaleDirectiveException -“PInvoke 限制:无法返回变体”
    • @Warren:检查我的声明,它返回一个整数。您必须使用滚动条才能看到它。
    • 好的,我现在赶上了。使用 Declare Ansi Function Thing Lib "Thing1.dll" (ByVal Command As String, ByVal Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer,我仍然得到 SEHException
    • 我的 dll 可能正在加载,并且崩溃现在在我的 DLL 中(令人费解)。明天上午我将调试并更新我的问题。
    • 就是这样。我的代码中出现了我最不希望发生的断言失败。
    【解决方案2】:

    您不能将StringBuilder 实例转换为string 实例,而是使用“ToString”方法将其转换回string 类型...这是dllCall 中的代码部分函数...

    retCode = 事物(命令、缓冲区、bufsz) 结果 = Buffer.ToString();

    【讨论】:

    • 那是我一个愚蠢的大脑放屁。现在我陷入了 marshall 异常(pinvoke 限制)异常。谢谢你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 2010-12-12
    • 1970-01-01
    相关资源
    最近更新 更多