Как мне импортировать и вызывать неуправляемый Cll-файл с ANSI C-строкой «char *», указатель строки из VB.NET? - PullRequest
2 голосов
/ 12 марта 2010

Я написал свою собственную функцию, которая в 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).

Ответы [ 2 ]

2 голосов
/ 12 марта 2010

Это зависит от того, как вы используете буферный аргумент в вашем 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

Обратите внимание на неоднозначность в возвращаемом значении длины.

0 голосов
/ 12 марта 2010

Вы не можете преобразовать экземпляр StringBuilder в экземпляр string, вместо этого используйте метод ToString, чтобы преобразовать его обратно в тип string ... вот часть кода в dllCall функция ...

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