【Excel(64bit) VBA】【Winsock API】recvfrmの第2引数(char* buf)にはVBAからByval string型で渡す必要がある件

 3日くらいドはまりした。しかも、あまり納得できていないがそういうものだと思うしかない。そして、調べてみたら、この件について思うことや対応策を考えている人がわずかにいて、安心した。

まず前提(自分の思い込みかもしれないが)

  • VB(VBA)を多少かじったものとして、Byvalは値渡し、Byrefは参照渡し、参照渡しであれば、処理結果が戻ってくるという認識を持っている。
  • C言語もちょっとだけかじったものとして、関数の引数にchar * とあれば char 型のポインタが必要だんだな、参照渡しだね と判断している。

この前提でrecvfrmの定義をmirosoftのサイトで確認すると、第2引数は char *buf となっているため、 参照渡しが必要だとわかる。

ちなみに第3引数 int len が 第2引数のサイズ(長さ)を示し、処理が成功すれば、第2引数 char *buf を先頭アドレス len バイト分のデータ電文をが受信できる。だったら、recvfrmの第2引数はbyref(参照渡し)指定だねと思うがこれが間違い。デバッグ中にExcelが突然死するほど目にあった。

正解はByval 指定

一例、まず定義では、第2引数はbyvalのstring型とする。

recvfromの呼び出し方は以下の通り

このパターンでサンプルコードを作成したら、確かに電文受信ができた。

その理由(Microsoftのサイトより、仕様確認)

Excel で DLL にアクセスする | Microsoft Docs

つまり、Byval Stringと定義して stringを渡せば、それがそのまま string型の先頭アドレス(ポインタ)がwsock32.dllのrecvfromにわたっているらしい。

これ正直、あまり納得できないわかりずらい仕様だと思う。

でも慣れていくしかないかな。新しい知識が増えたと思って

その仕様に関する先人の見解や対応策

http://chaichan.lolipop.jp/vbtips/VBMemo200708-26.htm

Win32APIの関数をVBで使うには… - Programming Field
VBでWin32APIの関数を呼び出す際に、全般的にどのようにDeclareステートメントを記述することで呼び出すことができるようになるかを解説しています。
Excel VBA で Win32API CreateFileA などの String型引数は、なぜ ByVal?
Excel VBA から Win32API を実行する場合の、String型引数に関する質問です。【背景】Win32API の CreateFileA,MoveFileA,DeleteFileA など、関数名最後が "A" となている関数の String型引数は、全て Declare... - その他(プログラミング・...
404 Not Found - Qiita - Qiita
「VB6.0 と VC++6.0 の連携」(1) VB業務アプリケーション開発研究室 − @IT
「VB6.0 と VC++6.0 の連携」に関する質問と回答の一覧です。(1) VB業務アプリケーション開発研究室 − @IT
Excel で DLL にアクセスする
Office 開発者クライアント VBA リファレンス

コメント

タイトルとURLをコピーしました