参照とポインタって…?

アバター
tk-xleader
記事: 158
登録日時: 14年前
連絡を取る:

参照とポインタって…?

投稿記事 by tk-xleader » 14年前

IUnknown.QueryInterfaceを見ててふと思った、なんで第一引数の型はREFIID(= GUID const&)なんだろう?
参照ってC++にしかないよね? なんて思っていたら、どうもWindowsでは参照もポインタも同じようにコンパイルされてしまうらしいのです。

そこでテストコード。DLL側はポインタで引数を受け取るようにします。これを呼び出し側で参照引数で呼び出して見ます。

DLL側

CODE:

//dllimpl.c
#include
#include
#include

int APIENTRY DllMain(HINSTANCE hInst,ULONG ulReason,LPVOID lpReserved){
	//警告回避
	(void)hInst;
	(void)lpReserved;

	//初期化
	switch(ulReason){
		case DLL_PROCESS_ATTACH:
			srand((unsigned)time(NULL));break;
	}

	return TRUE;
}

__declspec(dllexport) void __stdcall CreateRandomNumber(int* result){
	if(result!=NULL)*result = rand();
}
EXE側

CODE:

#include

extern"C"__declspec(dllimport) void __stdcall CreateRandomNumber(int& result);

int main(){
	//100回乱数を生成して表示する。
	for(int i=0;i<100;i++){
		int result=0;
		CreateRandomNumber(result);
		std::cout<<result<<std::endl;
	}
}
結果、何事もなかったかのようにビルド&実行が成功しました。これは知らなかったなぁ…
添付ファイル

[拡張子 zip は無効化されているため、表示できません]


アバター
GRAM
記事: 164
登録日時: 14年前

Re: 参照とポインタって…?

投稿記事 by GRAM » 14年前

知らなかった・・・
そんなことがあるのかw
(なぜだろう。質問掲示板にありそうな題名なのに tkmakwins15さんの記事だからちょっと読むのに覚悟をする自分がいる)
(・・・だがそれがいい)

アバター
tk-xleader
記事: 158
登録日時: 14年前
連絡を取る:

RE: 参照とポインタって…?

投稿記事 by tk-xleader » 14年前

参照がポインタで実装されているって言うのは想像はつくのですけれども、ユーザーコードでそのことを利用するというのはあまりしないですから、それが驚きの原因かも…
GRAM さんが書きました:(なぜだろう。質問掲示板にありそうな題名なのに tkmakwins15さんの記事だからちょっと読むのに覚悟をする自分がいる)
(・・・だがそれがいい)
ん!? そんなに僕の記事って読むのに覚悟いるんですか?
最後に編集したユーザー tk-xleader on 2011年7月15日(金) 01:11 [ 編集 1 回目 ]

ISLe
記事: 2650
登録日時: 15年前

Re: 参照とポインタって…?

投稿記事 by ISLe » 14年前

そもそもC++じゃないとIUnknown.QueryInterfaceをそのまま呼ぶことができませんよね。
Cからだと仮想関数テーブルを定義した構造体経由の呼び出し方がありますけど、余程の理由がない限りわざわざ使うことはないのではないでしょうか。

調べてみたらWindowsに限ったことではないみたいです。

main.cpp

CODE:

#include
extern"C" void CreateRandomNumber(int& result);
int main(){
    //100回乱数を生成して表示する。
    for(int i=0;i
void CreateRandomNumber(int* result) {
    if(result!=NULL)*result = rand();
}
上記のソースファイルを用意してUbuntuで、
gcc -c sub.c
g++ main.cpp sub.o
としたら実行ファイルが作れました。
ひとつのソースファイルに書くとエラーになるんですけどね。
(追記)
実行ファイルは正常動作しました。
最後に編集したユーザー ISLe on 2011年7月15日(金) 02:25 [ 編集 1 回目 ]

アバター
GRAM
記事: 164
登録日時: 14年前

RE: 参照とポインタって…?

投稿記事 by GRAM » 14年前

tkmakwins15 さんが書きました:ん!? そんなに僕の記事って読むのに覚悟いるんですか?
いえ、よく若干難易度の高いコードというか話題が載っているので、まだちょっと気合を入れないといけないんですよね。
何というか、技術書を開くときにはちょっとだけ心の準備が要るみたいなそんな感じですw

アバター
tk-xleader
記事: 158
登録日時: 14年前
連絡を取る:

RE: 参照とポインタって…?

投稿記事 by tk-xleader » 14年前

>ISLeさん
ISLe さんが書きました:そもそもC++じゃないとIUnknown.QueryInterfaceをそのまま呼ぶことができませんよね。
Cからだと仮想関数テーブルを定義した構造体経由の呼び出し方がありますけど、余程の理由がない限りわざわざ使うことはないのではないでしょうか。
C++以外の言語でも、IUnknown.QueryInterfaceを直接呼び出せるものはありますよ。たとえば、ActiveBasic,D言語などです。
今回これに気づいたのはD言語でCOMをいじってみようということを考えたからですね。
ISLe さんが書きました:調べてみたらWindowsに限ったことではないみたいです。
(~中略~)
上記のソースファイルを用意してUbuntuで、
gcc -c sub.c
g++ main.cpp sub.o
としたら実行ファイルが作れました。
ひとつのソースファイルに書くとエラーになるんですけどね。
コンパイルしてオブジェクトファイルにした時点で型情報は消えるので、ポインタ引数と参照引数のABIが同一の環境であれば動きうるのは動きうるのですが、規格上は保証はないんですよねこれ…
まぁ環境依存は確実なので、こんなことに規格なんて持ち出しても仕方はないんですけれども…

>GRAMさん
GRAM さんが書きました:いえ、よく若干難易度の高いコードというか話題が載っているので、まだちょっと気合を入れないといけないんですよね。
何というか、技術書を開くときにはちょっとだけ心の準備が要るみたいなそんな感じですw
なるほど、それ分かります。でも慣れてくると平気になってきますよ(たぶん)。

ISLe
記事: 2650
登録日時: 15年前

Re: 参照とポインタって…?

投稿記事 by ISLe » 14年前

ActiveBasicやD言語でも参照は使えないという話でしたか。
C/C++しか書かれてなかったので参照とポインタの互換性の話かと勘違いしてしまいました。

予想では__declspec(dllimport),__declspec(dllexport)が影響していると思ったんですが、ふつうにオブジェクト形式になった時点で欠落しているんだなあと再確認した次第です。
というか
extern"C" void CreateRandomNumber(int& result);
がエラーにならないのには理由がありましたっけ。

アバター
tk-xleader
記事: 158
登録日時: 14年前
連絡を取る:

RE: 参照とポインタって…?

投稿記事 by tk-xleader » 14年前

ISLe さんが書きました:extern"C" void CreateRandomNumber(int& result);
がエラーにならないのには理由がありましたっけ。
規格を参照してみました。JIS規格の7.5 「結合指定」にextern"C"などの規定が書かれているのですが、関数宣言において、C互換型以外の引数を持つことを明示的に禁止している規定は見つかりませんでしたし、そもそも言語結合をどのように処理するか?ということ自体が処理系定義なので、エラーにならなくても問題ないようです。
あえて言うなら、「エラーになる規格上の理由がないからエラーにならない。」というのが回答でしょうか…

ISLe
記事: 2650
登録日時: 15年前

Re: 参照とポインタって…?

投稿記事 by ISLe » 14年前

extern"C" はCの文法に制限するものではなく結合規則を指定するだけでしたね。
リンクできるのはたまたまで、処理系によってはリンクできないこともあるということですね。