1

私は、VB6 アプリケーションを VB.net に変換するという楽しい (そして、楽しいというのは骨の折れる退屈な作業です) 仕事をしています。このアプリケーションが行うことの 1 つは、c dll (そのうち 30 個) と通信することです。手作業で多くの構造と宣言を記述した後、自動化されたツールが時間を節約するのに役立つと判断したため、pinvoke ウィザード ツールを購入しました。

ヘッダー ファイルをスローして実行したところ、VB コードが正常に生成されましたが、使用方法がわかりません。例を挙げましょう。私が呼び出すメソッドの 1 つは 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 バイトを使用して、NULL で終了する文字列を表すにはどうすればよいですか?

4

1 に答える 1

1

質問へ:

1 バイトを使用して、NULL で終了する文字列を表すにはどうすればよいですか?

簡単な答えは「あなたはしない」です。

とにかく、それは実際にはコードで起こっていることではありません。まずByRef someVar As Byte、Byte を API に渡していません。バイトへのポインタを渡しています。したがって、ネイティブ側では、コードはそのバイトのアドレスを取得しています。そのアドレスが、文字列の文字を含むバイトのバッファ内 の最初のバイトを指し、(おそらく) null で終了している場合、その API がその内容をその null まで読み込んでそれに基づいて動作するのは簡単です。

そして、実際には C# で安全でないコード ブロックを使用したり、GCHandle ping や Marshal クラスまたは MarshalAs 属性で何かを使用して、StartSession(myParam1Buff[0], etc, etc);.

しかし、しないでください。ドキュメント (ヘッダー ファイルだけでなく) を読み、API が何を期待しているかを判断し、ドキュメントに基づいてUnmanagedTypeフラグが設定された正しい MarshalAs 属性で装飾されたインスタンスを使用するStringBuilderかを判断する必要があります。ほとんどの場合、それは.StringLPStr

于 2012-07-05T18:58:06.643 に答える