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が突然死するほど目にあった。
1 2 3 4 5 6 7 8 |
int recvfrom( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen ); |
正解はByval 指定
一例、まず定義では、第2引数はbyvalのstring型とする。
1 |
Public Declare PtrSafe Function recvfrom Lib "wsock32.dll" (ByVal SOCKET As LongPtr, ByVal buf As String, ByVal length As LongPtr, ByVal Flags As Long, fromAddr As SOCKADDR_IN, fromAddrSize As Long) As Long |
recvfromの呼び出し方は以下の通り
1 2 3 4 5 |
Const RecvBuffSize As Long = 2048 Dim recvBuffer As String * RecvBuffSize ~~ 略 ~~ recvResult = recvfrom(ListenSocketHandle, recvBuffer, RecvBuffSize, 0, remoteAddr, LenB(remoteAddr)) |
このパターンでサンプルコードを作成したら、確かに電文受信ができた。
その理由(Microsoftのサイトより、仕様確認)
1 2 3 |
C/C++ および VBA の引数の型 C/C++ と VBA の引数の型の宣言を比較するときには、次の点に注意が必要です。 VBA の <strong>String</strong> は、ByVal 渡しの場合はバイト文字列 BSTR 構造体へのポインターとして渡されます。<strong>ByRef</strong> 渡しの場合はポインターへのポインターとして渡されます。 |
つまり、Byval Stringと定義して stringを渡せば、それがそのまま string型の先頭アドレス(ポインタ)がwsock32.dllのrecvfromにわたっているらしい。
これ正直、あまり納得できないわかりずらい仕様だと思う。
でも慣れていくしかないかな。新しい知識が増えたと思って
その仕様に関する先人の見解や対応策
http://chaichan.lolipop.jp/vbtips/VBMemo2007–08-26.htm
Win32APIの関数をVBで使うには… - Programming Field
VBでWin32APIの関数を呼び出す際に、全般的にどのようにDeclareステートメントを記述することで呼び出すことができるようになるかを解説しています。
Excel VBA で Win32API CreateFileA などの String型引数は、なぜ ByVal?
Excel VBA から Win32API を実行する場合の、String型引数に関する質問です。【背景】Win32API の CreateFileA,MoveFileA,DeleteFileA など、関数名最後が "A" となている関数の...
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 リファレンス ドキュメント
コメント