pinvoke из vb.net с использованием структур при вызове

Я действительно борюсь со следующим вызовом pinvoke. Я пробовал множество разных способов сделать это, но до сих пор не радуюсь.

Вызов проходит, но я получаю сообщение «Неверный параметр» с предложением, что что-то не так со структурой, так как я просмотрел пример этого кода на С++, и все параметры верны.

Я был бы так благодарен за любую помощь, я уже сошёл с ума!

в заголовочном файле С++:

int __stdcall DVSNET_OpenChannel(HANDLE hServer,unsigned long nChannel,DVSNET_CHANNEL_INFO *pChannelInfo,HANDLE *phChannel);

typedef struct tagDVSNET_CHANNEL_INFO
{
    unsigned long lStructSize;
    unsigned long dwStreamNo;
    unsigned long nProtocol;
    HWND          hWndDisplay;
    unsigned long bPlayStart;
    unsigned long dwBackFrameCount;
    unsigned long dwFlag;
} DVSNET_CHANNEL_INFO;

Мои определения для импорта:

<DllImport("DVSNETClient.dll")> _
Public Shared Function DVSNET_OpenChannel(ByVal hServer As System.IntPtr, ByVal nChannel As UInteger, ByRef pChannelInfo As IntPtr, ByRef phChannel As IntPtr) As Integer
End Function

<StructLayout(LayoutKind.Sequential)> _
Public Structure tagDVSNET_CHANNEL_INFO
    Public lStructSize As UInteger
    Public dwStreamNo As UInteger
    Public nProtocol As UInteger
    Public hWndDisplay As IntPtr
    Public bPlayStart As UInteger
    Public dwBackFrameCount As UInteger
    Public dwFlag As UInteger
End Structure

Мой код вызова:

Private Sub OpenChannel()
    Dim intRet As Integer
    Dim ChannelInfo As New tagDVSNET_CHANNEL_INFO

    Dim HWD As New System.IntPtr

    ChannelInfo.lStructSize = System.Runtime.InteropServices.Marshal.SizeOf(ChannelInfo)
    ChannelInfo.nProtocol = 0
    ChannelInfo.dwStreamNo = 0
    ChannelInfo.dwBackFrameCount = 10
    ChannelInfo.hWndDisplay = HWD
    ChannelInfo.bPlayStart = 0 ' dont display
    'Channelinfo.dwFlag = 

    ' Initialize unmanged memory to hold the struct.
    Dim ptr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ChannelInfo))
    System.Runtime.InteropServices.Marshal.StructureToPtr(ChannelInfo, ptr, True)

    Dim nChannel As UInteger = 1
    intRet = TotemPoleLib.DVSNET_OpenChannel(hServer, nChannel, ptr, hChannel)

    '... snip ...
End Sub

Спасибо заранее!


person dunc    schedule 03.05.2011    source источник


Ответы (1)


Я не знаю синтаксиса VB.Net, но если вы понимаете C#, то вот правильные объявления P/Invoke для DVSNET_CHANNEL_INFO и DVSNET_OpenChannel:

[StructLayout(LayoutKind.Sequential)]
struct DVSNET_CHANNEL_INFO
{
    uint   lStructSize;
    uint   dwStreamNo;
    uint   nProtocol;
    IntPtr hWndDisplay;
    uint   bPlayStart;
    uint   dwBackFrameCount;
    uint   dwFlag;
}

static class DVSNETClient
{
    [DllImport("DVSNETClient.dll")]
    public static extern int DVSNET_OpenChannel(
        IntPtr hServer,
        uint nChannel,
        ref DVSNET_CHANNEL_INFO pChannelInfo,
        ref IntPtr phChannel
    );
}

Ваш DVSNET_CHANNEL_INFO выглядит нормально, но 3-й аргумент DVSNET_OpenChannel должен быть просто ref DVSNET_CHANNEL_INFO; вся маршалинг выполняется за вас автоматически, здесь нет реальной необходимости в классе Marshal. Единственное, что вам нужно сделать, это инициализировать ChannelInfo.lStructSize значением Marshal.SizeOf(typeof(DVSNET_CHANNEL_INFO)) перед вызовом DVSNET_OpenChannel. Вероятно, было бы разумно сделать это в конструкторе, отличном от используемого по умолчанию, для DVSNET_CHANNEL_INFO, но, учитывая, что это структура, конечно, нет способа принудительно использовать этот конструктор вместо неявного конструктора по умолчанию.

Обратите внимание, что семантически возможно, что pChannelInfo и/или phChannel должны быть out, а не ref, но это невозможно определить по сигнатуре DVSNET_OpenChannel. В любом случае использование ref будет работать независимо, хотя оно будет менее эффективным, чем использование out, если out действительно оправдано.

person ildjarn    schedule 03.05.2011
comment
фантастически, это работает удовольствие, спасибо! -Я думал, что уже пробовал это, прежде чем изменить структуру на метод ptr, но, очевидно, что-то пошло не так. Большое спасибо еще раз! - person dunc; 03.05.2011