2011-05-03 36 views
3

我真的很苦惱與以下pinvoke調用。我嘗試了許多不同的方式來做到這一點,但仍然沒有喜悅。從vb.net使用調用結構調用

該調用貫穿始終,但我收到一個'Bad parameter'消息,提示struct存在錯誤,因爲我已經運行了這個代碼的C++示例,並且參數都是正確的。

我會很感激任何幫助,我已經GOOGLE了自己已經瘋了!

在C++頭文件:

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 

提前非常感謝!

回答

1

我不知道VB.Net語法,但如果你瞭解C#,然後這裏有正確的P/Invoke的聲明DVSNET_CHANNEL_INFODVSNET_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顯示正常,但的第三個參數DVSNET_OpenChannel應該只是一個ref DVSNET_CHANNEL_INFO;所有的編組都是自動完成的,這裏沒有真正需要Marshal的課程。 只有您需要做的事情是在致電DVSNET_OpenChannel之前將ChannelInfo.lStructSize初始化爲Marshal.SizeOf(typeof(DVSNET_CHANNEL_INFO))的值。在DVSNET_CHANNEL_INFO的非默認構造函數中執行此操作可能是明智的,但考慮到它是一個結構體,當然沒有辦法在隱式默認構造函數上強制使用該構造函數。

需要注意的是語義上它可能是pChannelInfo和/或phChannelout而非ref,但它是不可能通過的DVSNET_OpenChannel簽名告訴。在任何情況下,使用ref都將起作用,儘管如果out確實是有保證的,那麼效率會比使用out效率低。

+0

太棒了,這是一個治療感謝! - 我以爲我已經嘗試過將這個結構改爲ptr方法,但是顯然在這個過程中出了問題。非常感謝! – dunc 2011-05-03 10:43:33