C プラグマのソースを表示
新しいページはコチラ
移動:
案内
,
検索
※このページではC言語にも存在していたという意味で記事タイトルがC プラグマになっていますが、<br /> [[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br /> <br /> <big><big>'''プラグマ'''</big></big> プラグマは、一般的に処理系独自のコンパイルオプションやコンパイル時の取り扱いをプログラムソースコード上で制御するためのディレクティブです。このように説明するとなんだか簡単なことを制御するだけのディレクティブに思えますが、VisualStudioでWindowsアプリを作成するようなプログラマにとっては、全てを理解することは非常に難しいことです。なぜなら、Windows独自の技術自体をコンパイルオプションによって制御するということですから、Windows OSの技術の中でも、通常のパソコン操作程度では聞いたこともないような技術について知る必要があることを含め、Visual Studioで設定可能なプロジェクトのプロパティの全てを理解していくのと等しいことだからです。プラグマによって制御できる全てを理解することは非常に難しいことですが、基本的に意識する必要のないコンパイルオプションもふんだんに含まれているので、深く理解をせずに、アプリケーションを作成する上で効率をあげるために理解するべき内容から理解していくことのほうが重要になります。 OS自体も人間には理解しにくい部分はなるべく意識せずにコンピュータを制御することを支援するために、作られているのですから、制御できるすべてを改めてプログラム側で制御する指示をすることを理解するのは、難しくて当たり前です。それでも、制御できる部分があるということは、一般的によく利用されるべき制御部分があることも確かなことでありまして、コンピュータを使って何をする人が多いのかを考えれば、インターネットをする人や文書を作成する人が多いことと同じで、プログラムを作成する際に制御されるべき部分についても、よく制御される部分とあまり制御されない部分とがあります。もちろん、どんなことにも対処できるプログラマになるにはすべてを理解した方がいいに決まっています。どこまで理解するべきかはプログラマ自身が決めることです。 ここでは、よく使われるであろうマイクロソフト固有のプラグマについて触れ、出来る限りの解説を長期間をかけて記載していきたいと思いますが、まずはプラグマによる制御の基本だけを触れて、Windowsアプリの記事を書くまでの間は、基本の部分以外については放置することになります。すべてを理解したい人は、MSDNによる解説とインターネットに散在している解説記事を閲覧して頂ければと思います(自分に言われなくても、勉学に励んでおられる人ならば、そうするにきまってるんでしょう。)。 *MSDNでのプラグマに関する説明ページ :https://msdn.microsoft.com/ja-jp/library/d9x1s805.aspx =='''#pragma'''== <nowiki>#</nowiki>pragmaディレクティブは半角スペースに続けてもう一つのワードと引数パラメータを伴って定義する形式のものがほとんどです。また、マイクロソフト固有の仕様ですが、<nowiki>#</nowiki>pragmaの代わりに__pragmaでも同様の機能として動作するようになっています。これはディレクティブとして先頭に使われる#以降の#はプリプロセッサ演算子の文字列化演算子として扱われることを回避するために用意されています。 ===#pragma comment=== *lib ====#pragma comment(lib, [” ”])==== <nowiki>#</nowiki>pragma commentはよく使われるプラグマの中のひとつで、その中でも1つ目の引数のlibと記述するパラメータを渡すものがよく使われていると思います。具体的には '''<nowiki>#</nowiki>pragma comment(lib, "拡張子libのタイプライブラリ名")''' として利用します。ライブラリの検索と読み込みについての指示を実行ファイル(.objや.oの拡張子がよく使われる)に記述するための指示です。リンク処理時に実行ファイルに記述されたライブラリ検索と読み込みを実行させることができるため、結果的に予め準備していたタイプライブラリの関数を利用することができるようになります。このような指示はVisualStudioではプロジェクトのプロパティでも同様に指定する手段が設けられています。 また、プロジェクトのプロパティで実行ファイルに記述されたライブラリの検索と読み込みの指示を無視するオプション /nodefaultlib も用意されているため、このオプションの内容に従ってリンクがなされた場合、ライブラリは読み込まれません。もしライブラリを読み込まないでリンク処理を実行するとエラーになるような場合には当然、関数(シンボル)が見つからない旨のエラーが発生しますので、別の方法でライブラリの読み込まないオプションを利用したことを補う必要が発生します。更には /Zl オプションを使うと実行ファイルにライブラリの検索と読み込みの指示についての書き出しがされないようにすることもできます。つまり、#pragma comment(lib, "xxxxx")の指示が無視されます。/Zlオプションは不要意にライブラリを読み込んで実行ファイルが肥大化するのを防ぎ、スペースを節約する役割のモノです。ライブラリの読み込み順序や読み込まれる部分を思慮深く、指定することを制御することを実現するための仕組みです。このあたりのオプション関連の動作も含めて一連の処理を理解しようとすると非常に複雑なものになります。このような問題からライブラリが見つからない場合、実行ファイルからリンク処理をするときには関数名が若干、修飾変換された関数名になっているため、少し変化した関数名で関数が見つかりませんというエラーが表示されます。こういった表示が出る場合は、これらのライブラリ読み込みに関するオプションやpragmaでの制御がうまくいかずにリンク処理が失敗していることを意味しますので、何が欠けているのか?その関数は何と言うライブラリで提供されていて、どこで読み込みを指示しているか?どのタイミングで読み込まれるか?きちんと読み込まれるかまでを再検討する必要が発生します。人からもらったプロジェクトをそのままコンパイルしてうまく動かない場合は、だいたいこのあたりの記述で問題が起こっていたり、環境変数LIBへのパス設定不足やライブラリの不足あるいはライブラリパスの変更による問題が発生していることがほとんどです。 プロジェクトファイルを配布しているにも関わらず、受け取ったファイルがそのまま動かせなかったり、プロジェクトの展開方法についての指示がないというものは、プロジェクト配布者に落ち度があると考えてよいですが、それが、意図的なのか、能力不足なのかは知る由はありません。プロジェクトファイルを公開しようとしているスタンスだけを評価し、プロジェクト配布者の能力や人柄を判断することになります。自分の場合はプロジェクトの中身を精査して、ライブラリパスに個人的なフォルダ設定を残したまま配布してる場合は、こういうものにはあまり関わりたくないと感じるほうですね。プロジェクトを完成させたくらいだから能力はあるんだろうけど、こんな状態で配布してるプロジェクトと関わると最終的には、どうせろくなことにならないと、そのように感じてしまいます。それが意図的であるなら尚更です。 このサイトを含め、ただで勉強しようとすると、結局は時間の無駄に終わることはよくあります。学ぶべき手段を選び間違えた自分を悔いるしかないです。そうならないように、できるだけ有用なものにはしていきたいとは思いますが、違う生業(なりわい)のかたわらの執筆です。なにぶんお聞き苦しい点も多々あろうかとは存じますが、耳を傾けていただければと思います。 文字列操作について触れた記事で、ICUのライブラリを使った記事があります。そこでは具体的には、以下のように利用しました。 <syntaxhighlight lang="cpp" line start="1"> //ICU ucnvプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定) #include <unicode/ucnv.h> //ucnv文字コード変換ライブラリヘッダ #include <unicode/translit.h> //文字変換ライブラリヘッダ #include <unicode/regex.h> //正規表現 #include <unicode/ucsdet.h> //文字コード判定 #include <unicode/ucal.h> //文字コード判定 #include <unicode/uclean.h> //u_cleanup関数 /* for uloc_getDefault() */ #include <unicode/uloc.h> #include <unicode/calendar.h> #include <unicode/smpdtfmt.h> //#include "unicode/utypes.h" //#include "unicode/locid.h" //#include "unicode/unistr.h" //#include "unicode/tzfmt.h" //#include "unicode/tznames.h" #ifdef _DEBUG #pragma comment(lib, "icudt.lib") #pragma comment(lib, "icuucd.lib") //ICU ucnvを使うために必要なライブラリ #pragma comment(lib, "icuind.lib") //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も #pragma comment(lib, "iculed.lib") #pragma comment(lib, "iculxd.lib") #pragma comment(lib, "icuiod.lib") #pragma comment(lib, "icutud.lib") #else #pragma comment(lib, "icudt.lib") #pragma comment(lib, "icuin.lib") //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も #pragma comment(lib, "icuuc.lib") //ICU ucnvを使うために必要なライブラリ #pragma comment(lib, "icuio.lib") #pragma comment(lib, "icule.lib") #pragma comment(lib, "iculx.lib") #pragma comment(lib, "icutu.lib") #endif //Data Library icudtXX(d).dll icudt(d).lib //Common Library icuucXX(d).dll icuuc(d).lib //Internationalization(i18n) Library icuinXX(d).dll icuin(d).lib //Layout Engine iculeXX(d).dll icule(d).lib //Layout Extention Engine iculxXX(d).dll iculx(d).lib //ICU I/O(Unicode stdio) Library icuioXX(d).dll icuio(d).lib //Tool Utility Library icutuXX(d).dll icutu(d).lib //ICU ucnv _End #include "UnicodeConverter.h" </syntaxhighlight> このようにプラグマと#ifディレクティブのようなプリプロセッサ構文制御やマクロ定義といったディレクティブを併用して、適切なライブラリがロードされるようにプログラムソースで記述することができます。_DEBUGというマクロ定義はVisualStudioではプロジェクトの中でもデバッグモードというプログラム作成時の不具合箇所発見をするための方式を利用している作業のときだけ定義されるマクロで、要するにモード毎に異なるライブラリを使っています。ライブラリにもデバッグ向けのライブラリとリリース向けのライブラリが分かれている場合があり、デバッグ向けのライブラリを使っているとデバッグをしやすいように例外処理による警告が発動するように作られていて、ライブラリ利用中に発生した問題でも、どのような問題が起こったのかをわかりやすく支援してくれる形式になっています。 もちろん、プロジェクトのプロパティもリリースモード、デバッグモードで別々に設定することができますので、個別にプロパティ部分の利用するライブラリ名を記述する欄に記述することができます。 この他にも、#pragma comment()のディレクティブには第一引数に指定できる値があり、 *compiler *exestr もう使われなくなる予定なので説明を省略。 *linker *user があります。それぞれについても以下に説明します。 ====#pragma comment(compiler)==== 使い方は、決まっていて、以下の通りで、第二パラメータはありません。実行ファイル(.objファイル)にコンパイラのバージョン情報が記述されます。Visual Studioのリンク処理では実行ファイル(.obj)に記述されているコンパイラのバージョンに不一致があればエラーとなります。したがって、2つ以上のヘッダファイルがあるプロジェクトで、一度ビルドしたあと、このプラグマを一つのヘッダファイルだけに記述してビルドした場合、objファイルの中のコンパイラバージョンの記述に不一致が発生し、エラーが発生します。リビルドするとこの問題は解決します。逆にある一つのヘッダファイルだけにこのプラグマがある状態で、一度ビルドしたプロジェクトから、このプラグマを消すと同じようにエラーが発生します。この場合もリビルドすることによってコンパイラバージョン情報に関する整合性エラーが解決します。 ====#pragma comment(linker, [” ”])==== ====#pragma comment(user, [” ”])==== ===#pragma once===
C プラグマ
に戻る。
個人用ツール
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ