如何使用VB.NET中的ANSI C字符串“char *”指针字符串导入和调用非托管C dll?

时间:2010-03-11 21:37:51

标签: vb.net dll unmanaged dllimport

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

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用户习惯的正常事情)。

2 个答案:

答案 0 :(得分:2)

这取决于您在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值中的歧义。

答案 1 :(得分:0)

您无法将StringBuilder实例转换为string实例,而是使用'ToString'方法将其转换回string类型...这里是dllCall函数中的代码...

retCode = Thing(Command, Buffer, bufsz)
Results = Buffer.ToString();