使用Pinvoke传递LPBYTE时

时间:2012-07-03 17:29:56

标签: c# .net vb.net pinvoke

我将VB6应用程序转换为VB.net令人愉快(并且令人愉快,我的意思是单调乏味)。此应用程序执行的操作之一是与c dll(其中30个)进行通信。在手工编写了许多结构和声明之后,我决定使用自动化工具来节省时间,因此我购买了pinvoke向导工具。

我跑了它的头文件,它成功生成了VB代码,但我不明白如何使用它,让我举个例子。我称之为StartSession的方法之一。 在C中,标题代码是

WORD APIENTRY StartSession 
(LPBYTE lpbReturnCode,
LPBYTE lpbErrorMessage,
LPBYTE lpbApplName,
LPBYTE lpbRegionName,
LPBYTE lpbSessionID, 
LPBYTE lpbDataTrunc,
LPBYTE lpbSessionToken,
LPBYTE lpbStandardWait,
LPBYTE lpbVersion,
LPBYTE lpbEnvironment,
LPBYTE lpbESILogonOnly,
LPBYTE lpbMetadataSource,
LPWORD lpbMetadataCacheCount); 

当我用手重写这个函数时,我把它写成了

Declare Function StartSession Lib "chat2.dll" (ByVal ReturnCode As String _
                                               , ByVal ErrorMsg As String _
                                               , ByVal ApplicationName As String _
                                               , ByVal RegionName As String _
                                               , ByVal EmulatorSessionID As String _
                                               , ByVal DataTruncationFlag As String _
                                               , ByVal SessionToken As String _
                                               , ByVal StandardWait As String _
                                               , ByVal ApplicationVersion As String _
                                               , ByVal Environment As String _
                                               , ByVal ESILogonOnly As String _
                                               , ByVal ScreenDescDataSource As String 
                                               , ByRef ScreenDataCacheCount As Short) 

当我调用此方法时,我提交了null终止的char数组 恩。

Dim param1 As Char()
param1(0) = "c"c
param1(1) = "a"c
param1(2) = "t"c
param1(3) = ChrW(0)
StartSession (param1,...)

pinvoke向导生成以下存根

<DllImport("chat2.dll")> _
Public Function StartSession( _
        ByRef lpbReturnCode As Byte _
        , ByRef lpbErrorMessage As Byte _
        , ByRef lpbApplName As Byte _
        , ByRef lpbRegionName As Byte _
        , ByRef lpbSessionID As Byte _
        , ByRef lpbDataTrunc As Byte _
        , ByRef lpbSessionToken As Byte _
        , ByRef lpbStandardWait As Byte _
        , ByRef lpbVersion As Byte _
        , ByRef lpbEnvironment As Byte _
        , ByRef lpbESILogonOnly As Byte _
        , ByRef lpbMetadataSource As Byte _
        , ByRef lpbMetadataCacheCount As Short _
        ) As Short
End Function

如何使用单个字节表示以空字符结尾的字符串?

1 个答案:

答案 0 :(得分:1)

问题:

  

如何使用单个字节表示以null结尾的字符串   字符?

简单的答案是“你没有。”

无论如何,这并不是代码中发生的事情。首先,ByRef someVar As Byte没有将Byte传递给API。它将指针传递给一个字节。所以在本机端,代码获取该字节的地址。现在,如果该地址将第一个字节指向包含字符串字符的字节缓冲区并且(可能)以空值终止,则该API很容易将该内容读取到该空并作用于它。

你实际上可以在C#中使用不安全的代码块,或者使用GCHandle pinng或Marshal类或MarshalAs属性中的某些东西来模仿StartSession(myParam1Buff[0], etc, etc);之类的东西。

但不要。您需要阅读docos(不仅仅是头文件)并确定API的期望,并使用带有UnmanagedType标志的正确MarshalAs属性修饰的StringBuilder或“String实例基于doco设置。最有可能的是,LPStr