
Excel VBA から Win32API を実行する場合の、String型引数に関する質問です。
【背景】
Win32API の CreateFileA,MoveFileA,DeleteFileA など、関数名最後が "A" となている関数の String型引数は、全て Declare文で ByVal と宣言しないと上手く動作しません。
しかし VisualC++ のヘッダファイルでこれらの "A" 付き API の宣言を見てみると、文字列型の引数は全てアドレス渡しとして宣言されています。BVA での上記の宣言と矛盾しており、ByVal で上手く動作するのが不思議でなりません。
また VC++ で自分で作成した DLL関数の文字列型引数の場合は、BVA のDeclare文で ByRef と宣言しなければ上手く動作しません。これは上記の VC++ ヘッダファイルの API関数の宣言と辻褄が合っており、やはり、Declare文で "A"付き APIの場合に ByVal としなければならない事が矛盾しているとしか思えません。
【質問】
いったいこれは、どうなっているのでしょうか??
この場合("A" 付き API の場合)、どうして ByRef でちゃんと動くのでしょうか?
また String型の場合 ByRef では効率が悪いと思うのですが、なぜ ByRef が採用されているのでしょうか?
サルにでも分かるように説明して頂ければ幸いです。
【私の知識レベル】
C++ ではなく C言語 においては、アセンブラレベルでのコード及び動作を理解しております。
オブジェクト,クラス,メソッドなどの用語は一応理解しているつもりですが、C++ ならではのオブジェクティブな言語仕様は理解していません。
へんな質問かも知れませんが、よろしくお願いします。
No.1ベストアンサー
- 回答日時:
Win32APIに文字列を渡すには、ヌルで終端された文字列の先頭アドレスを指定します。
つまり、Cでいうところの char[] を渡します。
それに対してVBのString型は、直接には文字列データを持っていません。
String型変数には、文字列の先頭アドレスと文字列の長さが入っていて、本当の文字列データはどこか別の所に有ります。(VBが自動的にAlocateしたメモリに入る)
なので、String型変数のByRefを取って渡しても、APIは正しい文字列データを取得できません。
それに対してString型変数のByValを取ると、文字列の先頭アドレスが取得できるので、APIにそのまま渡せます。
この回答への補足
ご回答まことに有り難うございます。
まず自分の質問の訂正です。
"【質問】" のエリアの "ByRef"(3箇所)は "ByVal" の間違いです(恥)
申し訳ありません。
Basicの文字列変数の内部での持ち方、なんとなく思い出してきました。Basicをやっていたのは8bitの時代のことだったので、すっかり忘れていました。文字列変数の内部表現は今でも昔のそれを引き継いでいるのですね。
もう一つの疑問の APIのDLL と 自作DLL との違いですが、APIは確かPASCAL I/F でしたっけ。それに対して自分のDLLは extern "C" とかやっていたような気が... 同じDLLでも違う I/F になっている気がしてきました。
どうもVBAのDeclare文のところで、色んなI/Fへの辻褄あわせがなされているようですね。
もう少し色んな方の回答を待ってみます。
有り難うございました。
ご回答まことに有り難うございました。
またお礼が遅くなりすみません。
自分でちゃんと調べたいとは思うのですが、昔ほどのヒマも気力もなく、今はANo.2の方の補足に書いたような、私の勝手な解釈でとりあえず納得することにしました。
Basicの文字列変数の内部形式を思い出させて頂きました。(もしかしてVBやVBAは違うかも?)
有り難うございました。
No.2
- 回答日時:
VB6とVC6を使用していたころ私もこれが気になり調べたことがあります。
#確か、VB6の場合は、Win32APIにStringを渡す場合に一度(内部で)変換しているので、記述としてはByValで、内部の変換後は結果的にAPIに対してByRefになっていたような記憶があります。
それらしい記述を探してみましたが、明確に書いたのもを見つけられませんでした。
以下のサイトに一部それらしい記述があります。
http://www5.ocn.ne.jp/~kansroom/vbtips/waza14.htm
ただ、EXCEL VBAでも同様かまでは判りません
この回答への補足
ご回答まことに有り難うございます。
まず自分の質問の訂正です。
"【質問】" のエリアの "ByRef"(3箇所)は "ByVal" の間違いです(恥)
申し訳ありません。
BasicのDeclare文の箇所では、Basic以外の色んなI/Fへの辻褄あわせが内部でなされているということ、なんとなく分かってきました。有り難うございます。
また ANo.1の方への補足にも書きましたが、自作のDLLはAPIのDLLとは I/Fが違っているような気がしてきました。自作では extern "C" とかしていたような気がします。
どうも Declare文での(少なくとも文字列型変数の)ByVal,ByRefは、本来の意味で解釈しない方が良さそうですね。
今の所の自分なりの解釈としては、文字型変数で ByValとあれば API向けのI/F合わせを、ByRefとあれば CライクなI/F合わせをしているのかなと。
もう少し色んな方の回答を待ってみます。
有り難うございました。
ご回答まことに有り難うございました。
またお礼が遅くなりすみません。
自分でちゃんと調べたいとは思うのですが、昔ほどのヒマも気力もなく、今は補足に書いたような勝手な解釈で、とりあえず納得することにしました。
ANo.1の方の回答と優劣は付けられなかったのですが、先に回答下さったとの理由でANo.1の方に20ポイントとしたことを、ご了承下さい。
有り難うございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- Excel(エクセル) Excelの関数について 3 2022/11/13 23:47
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- Visual Basic(VBA) VBA初心者です 検索した数字の行に色をつける 5 2023/02/13 14:22
- Excel(エクセル) Excel 、この式はどのように解釈すればいいのでしょうか 4 2023/02/03 08:53
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- Visual Basic(VBA) Vbaで数式をポーランド記法に変換するコードを作って実行しようとするとフリーズします。 1 2022/05/24 17:53
- Excel(エクセル) エクセルVBA、ファイル名をセルの値で保存の方法を教えてください。 おそれいります。こちらで数々のエ 6 2023/06/30 22:17
- Visual Basic(VBA) 【再々投稿】VBAのプログラムで動作しなくて困っています 8 2022/10/14 09:06
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・思い出すきっかけは 音楽?におい?景色?
- ・あなたなりのストレス発散方法を教えてください!
- ・もし10億円当たったら何に使いますか?
- ・何回やってもうまくいかないことは?
- ・今年はじめたいことは?
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・【大喜利】【投稿~1/31】『寿司』がテーマの本のタイトル
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・【大喜利】【投稿~1/20】 追い込まれた犯人が咄嗟に言った一言とは?
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・【大喜利】【投稿~1/9】 忍者がやってるYouTubeが炎上してしまった理由
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルでアルファベットか数...
-
【Excel VBA】複数ある特定の文...
-
EXCELで=より左の文字を一括で...
-
エクセルでSQLでいうところの「...
-
文字列からタブコードを取り除...
-
CStringの文字列検索&抜き出し...
-
VBA2005 16進を2桁で表示したい。
-
同一セル内に関数と文字列を同...
-
アクセスでのインポート時の改...
-
変数内に入った文字列の結合 UWSC
-
ExcelのVBAにて、文字列データ...
-
【Teratermマクロ】文字列の分...
-
エクセルで文字列の最大値を抽...
-
急ぎです、大学数学再帰の問題...
-
UWSCの基本的な文字列操作
-
VBAでCSVを文字列として取り込...
-
VB2005とADO.NETを使った時のS...
-
文字列のエスケープ処理
-
OnTime 使用時のプロシージャへ...
-
VBA テキストボックスの計算
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルでアルファベットか数...
-
EXCELで=より左の文字を一括で...
-
VBAでの Replace関数で、ワイル...
-
文字列からタブコードを取り除...
-
エクセルで文字列の最大値を抽...
-
Excelで指数表現しないようにす...
-
Excelで3E8を3.00E+8にしない方...
-
Left関数とRight関数を合わせた...
-
エクセル 数値データを桁をそ...
-
エクセルで文字列をtxtファイル...
-
VBA2005 16進を2桁で表示したい。
-
【Excel VBA】複数ある特定の文...
-
同一セル内に関数と文字列を同...
-
MS SQLServer のSQLで文字列の...
-
C#で年月を比較する
-
アクセスで特定の数字以外(複...
-
VBの「As String * 128」とは?
-
ORCLEでの小数の表示方法の変更...
-
Msgboxの×が押されたとき
-
aaa.bbb.ccc という、「ドット...
おすすめ情報