передача параметров в неуправляемый C api от vb.net - PullRequest
1 голос
/ 03 марта 2010

Мне нужно вызвать функцию в неуправляемом .dll, написанном на C lang с vb.net. Объявление функции выглядит следующим образом

LONG _stdcall ReadInfo (символ * ответ);

Теперь поведение этой функции заключается в том, что она копирует некоторые данные в аргументе «reply» и возвращает числовое значение, которое сигнализирует о ее состоянии «пройти / не пройти». Как передать ему строковый объект, чтобы он мог копировать данные. Вот как я получаю доступ к этой функции.

Dim str as String obj.ReadDeviceInfo (ул)

и библиотека доступна таким образом ...

Public Declare Auto Function LoadLibrary Lib "kernel32" (ByVal libFilePath As String) As Integer

Public Declare Function GetProcAddress Lib "kernel32" (ByVal ModuleHandle As Integer, ByVal ProcName As String) As Integer

Public Declare Function FreeLibrary Lib "kernel32" (ByVal ModuleHandle As Integer) As Integer


Public Function ReadDeviceInfo(ByRef reply As String) As Integer

    Dim MethodPointer As Integer
    MethodPointer = GetProcAddress(ModuleHandle, "ReadInfo")
    Dim deviceInfo As ReadInfo = Marshal.GetDelegateForFunctionPointer(MethodPointer, GetType(ReadInfo))
    Return deviceInfo.DynamicInvoke(reply)

End Function

Когда вызов завершается, возвращенное состояние абсолютно нормально, но в строке "str" ​​ничего нет. Что я пропускаю? Я не уверен насчет строкового объекта, который я передаю в качестве аргумента. Есть мысли ...

Ответы [ 3 ]

3 голосов
/ 03 марта 2010

Строки в .NET являются неизменяемыми. Попробуйте передать StringBuilder:

Public Function ReadDeviceInfo(ByRef reply As String) As Integer    
    ...

    Dim sb As New StringBuilder(1000)
    result = deviceInfo.DynamicInvoke(sb)

    reply = sb.ToString()
    Return result
End Function

Из MSDN Magazine :

Если можно ввести строковый параметр и / или вывод, затем используйте Тип System.StringBuilder. Тип StringBuilder - полезный класс тип библиотеки, которая поможет вам построить струны эффективно, и это происходит с отлично подходит для передачи буферов нативным функции, которые функции заполняют строковые данные от вашего имени. Однажды Вызов функции вернулся, вам нужно только вызов ToString на Объект StringBuilder для получения строки объект.

В качестве альтернативы, закрепите массив символов и передайте его IntPtr.

0 голосов
/ 01 января 2013

Эти хорошо используемые функции демонстрируют, как преобразовать строку в байтовый массив и передать ее управляемой функции c ++ в виде закрепленного IntPtr:

Public Function b_fromString(ByRef str As String) As Byte()
    If Not str Is Nothing Then
        Return System.Text.Encoding.Default.GetBytes(str, 0, str.Length)
    Else
        Return New Byte() {}
    End If
End Function

Public Function cString(ByRef theString As String) As IntPtr
    Dim GC As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(b_fromString(theString & Chr(0)), System.Runtime.InteropServices.GCHandleType.Pinned)
    Dim ret As IntPtr = GC.AddrOfPinnedObject
    GC.Free()
    Return ret
End Function

Этот стиль функции можно использовать в управляемой оболочке c ++:

long libinterface::loadData(System::IntPtr bytes, long length)
{   return lib->functionName((char*)bytes.ToPointer(), length);
}

Длина строки обычно необязательна при использовании строки с нулевым символом в конце. Полезно, если не идеально.

Представлено для справки.

дополнительно - загрузка других массивов и растровых изображений:

    Public Sub New(ByRef _obj As Array, ByRef read As Boolean, ByRef write As Boolean)
        Me.size = Marshal.SizeOf(_obj(0))
        Me.count = _obj.LongLength
        Me.ptr = GCHandle.Alloc(_obj, GCHandleType.Pinned)
        Me.id = lib.addBuffer(count * size, read, write, ptr.AddrOfPinnedObject)
    End Sub

    Public Function getimgPtr(ByRef img As Bitmap) As IntPtr
        Dim f As System.Drawing.Imaging.BitmapData = img.LockBits(New Rectangle(0, 0, img.Width, img.Height), Imaging.ImageLockMode.ReadOnly, img.PixelFormat)
        getimgPtr = f.Scan0
        img.UnlockBits(f)
    End Function
0 голосов
/ 04 марта 2010

Используйте PInvoke Interop Assistant , чтобы автоматически преобразовать функцию C в объявления PInvoke.

Если у вас есть более детальное определение в «возвращаемых данных», поместите это в PInvoke Assistant. Например, он может преобразовывать определения структуры.

...