我将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
如何使用单个字节表示以空字符结尾的字符串?
答案 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
。