且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-12 17:09:21

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

 公共类dllInvoker 
声明Ansi函数Thing LibThing1.dll(ByVal Command As String, ByVal缓冲区作为StringBuilder,ByRef BufferLength As Integer)As Integer

共享函数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(命令,缓冲区,长度)
结果= Buffer.ToString()
Debug.Assert(Results。长度=长度)
返回retCode
结束函数
结束类

请注意返回的长度值中的歧义。


I have written my own function, which in C would be declared like this, using standard Win32 calling conventions:

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

I have the following amount of Visual Basic code figured out, which should import the DLL file and call this function, wrapping it up to make it easy to call Thing("CommandHere",GetDataBackHere).

UPDATE: This code is now a working solution, as shown here:

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

I got the code to build by following the help received here, and then I had forgot the As Return Type (which got me a MarshalDirectiveException PInvokeRestriction). Then I had an assertion failure inside my DLL, which lead to an SEHException. Once fixed, this works BEAUTIFULLY. Thank you folks. There are newsgroups where people are saying this can not be done, that Visual Basic only loads managed DLL assemblies (which I guess is the normal thing most Visual Basic users are used to).

It depends on how you use the buffer argument in your C code. If you only pass a string from your VB.NET code to your C code then declaring it ByVal String is good enough. If however you let the C code return a string in the buffer then you have to declare it ByVal StringBuilder and initialize it properly before the call. For example:

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

Note the ambiguity in the returned Length value.