静的/動的リンクライブラリについて

このQ&Aのポイント
  • Pythonのctypesを使っていて気になったこと
  • 静的リンクライブラリ(.lib)の対応についての疑問
  • dllとlibの利用可能性についての質問
回答を見る
  • ベストアンサー

静的/動的リンクライブラリについて

Pythonのctypesを使っていてふと気になったので質問させていただきます。 Cと少々Java、程度の経験しかなかった私にとって、ctypesによって「Cのデータ型を利用できる」「dllをロードして、エクスポートされている関数を使用できる」というのは衝撃でした。 しかし、考えてみれば、仕組みとして理解できなくもない・・・かな?と現在は思っています。 ただ気になったのは、  ・どうして静的リンクライブラリ(.lib)の方は対応してないの? ということです。 [質問1]これは原理的に不可能なのでしょうか、それともctypesやPythonの仕様としてできないだけなのでしょうか。 (おそらくは「原理的に不可能」なのだろう、と個人的には思っておりますが・・・。) 以下は私の中の解釈ですが、 ・マシン語として実行可能な形式になっているdllは、実行時のリンクの機構さえ整っていれば別にC言語でなくともロードや中身のコードを利用することはできる。 ・また、Cのデータ型についても、要は型のバイト数やフォーマット(つまり内部的な扱われ方)をPythonインタプリタが押さえていれば良い話であるから、PythonでCの型を使用することは原理的に可能。 さて、 [質問2]それではlibはどうか。 libもコンパイル済みのものであるなら、Python(またはC以外の言語)からlib内のコードを利用することはできるのではないか? どちらかのみの回答でも結構です。 また、解釈の誤りについてのご指摘や、リンクライブラリの仕組みを解説したページを教えてくださると助かります。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.2

動的ライブラリは本質的に実行可能プログラムです。一部参照が未解決の場合がありますが、それらはローダで解決できるようになっています。Windows DLLの場合、C形式(cdecl)やC++形式(stdcall)といったエントリポイント形式が決まっているので、メモリにロードしてエントリポイントを適切に呼び出せば使えます。 静的ライブラリは機械語プログラムの断片に過ぎません。変数や関数の参照解決ができていませんので、そのままでは実行できず、リンカと呼ばれる開発ツールによって実行可能プログラムに変換しないと使えません。Python実行環境はリンカを内蔵していないので静的ライブラリを使うことはできません。なお、一般的に静的ライブラリの構造は開発ツールにより異なるので、開発ツールごとに個別のリンカが必要です。 # 例えばVisual C++(.lib)とCygwin gcc(.a)では違う

htk433
質問者

お礼

リンクを行う機構が備わっていればPythonでも.libのコードを組み込むことは可能・・・。 ただPythonにはそういうものはないので、やりたければ自分で実装・拡張してくださいよ、と。そして静的ライブラリは形式によって内部の構造も異なるし、動的ライブラリの方が主流(これはどこかのページで見ただけですが)であることからコスト的にもあんまり見合わない。・・・と、私なりに解釈しました。 私が何に疑問を感じていたのか。というのが、寄せられた回答を咀嚼するうちにはっきりしてきた気がします。 が、それはまた別の質問として立てさせていただくことにします。 回答ありがとうございました。

その他の回答 (1)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

Python-C APIの資料は読んだことありますか? 例えば http://www.python.jp/doc/release/extending/index.html http://www.python.jp/doc/release/c-api/index.html PythonからCの関数が呼び出せる、といっても、なんでもかんでも使えるわけではありません。 直接呼び出すためには、Pythonの規則にしたがう必要があります。 正に「Cで書いてあるけど、Pythonのモジュール」です。 静的ライブラリというのは、それ単独で利用できるものではありません。リンクして初めて利用できるものです。これは、Pythonだから、というわけではなく、Cでも使う場合でもそうです。 Cで分割コンパイルはやったことありますか?あのときできる .objファイルを一つにまとめただけのものだと考えていればよいです。 Pythonから使おうとするなら、Pythonの実行ファイルをビルドする際に一緒にリンクする、と言った方法でなければ、利用できません。 あるいは、Pythonから呼び出せるDLLをビルドする時に一緒にリンクするか、ですが、これはDLLを作るときに極普通に使われている方法です。 どちらにしても、Pythonから呼び出すための専用の関数の用意も必要です。 # .lib,DLLとあることから、Windowsをお使いと判断しました。

htk433
質問者

お礼

回答ありがとうございます。 Python-C APIのページは読んだことがなかったです。 Pythonの正体(?)を知らないままなんとなく触っていたもので・・・Python <--> C の間でいろいろできるのも(理屈はさておき)得心できました。 (少なくとも、Windowsの).libの場合は(Cでもやるように)通常通り実行ファイルのビルド時に組み込むしかない、ということですね。 ※そうですね、Windowsです。その辺はLinuxでも良かったのですけど、プラットフォームによる違いは今回そこまで重要でなかったので。 Windows前提で書いたものでしたが、少々言葉足らずでしたね;

関連するQ&A

  • ライブラリ内の処理中におけるライブラリリンクについて

    VC2005を使用しています。 ライブラリからライブラリファイルって使用できるんでしょうか? (例) A.lib内の処理に、B.DLLを明示的に読み込み処理 ----------------- <A.lib内の処理> hDLL = LoadLibrary("B.dll"); // DLLのロード if (hDLL != NULL) { ~ 処理実行 ~ } ----------------- 私の環境で何度やっても、GetLastErrorにて、 "7E"(ERROR_MOD_NOT_FOUND)が出力されます。 ロードしているパスに、B.dllは必ずあります。 上記の例は明示的リンクですが、暗黙的リンクでもかまいません。 ライブラリ処理の中でライブラリファイルを使用するには、 どうすれば良いでしょうか。 もしかして、ライブラリ内で他のライブラリを使用できない 等のオチもあるのでしょうか...。

  • 静的リンクライブラリについて

    WindowsのライブラリにDLLやLIBといった形式があり、それぞれ「動的リンクライブラリ」「静的リンクライブラリ」となっていますが、 静的リンクライブラリとしてビルドされたライブラリを、動的に実行プログラムにリンクさせることは(Cやアセンブラなどの)実装次第で可能なのでしょうか? ビルド時にリンカがやってくれてることを実行時に行えればOK・・・という素直な話ではないのでしょうか。DLLも実行時にGetProcAddress()などを使ってアドレス解決をするわけですし、LIBでも同じことをするのは不可能ではないのでは?と思ったのです。 ※動的/静的リンクの概念や具体的な使用方法などはネット上で調べることができましたが、中身にまで踏み込んだ解説をしているページには巡り合えませんでした。そういう具体的な解説のあるページの紹介だけでもとても助かります。また、「根本的に思い違いをしてるんでは?」というご指摘も非常に助かります。 ※私自身↑に対する需要はないのでコスト・メリットとかは度外視です。興味本位というやつです。 ※別段、Windowsやライブラリの形式にこだわりがあるわけではないですが、これが一番メジャーだろう、ということでWindowsのDLL/LIBを対象に質問させて頂きました。 よろしくお願いします。

  • Qtライブラリを静的にリンクしたい

    Qt 5.11.0 を使ってGUIアプリをつくろうとしているのですが、実行時の問題があります。 ソースは初心者用のサンプルソースコードで、Qt Creator を使って以下の「main.cpp」を作成しました。 #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } ウインドウ生成は「mainwindow.cpp」で、 #include "mainwindow.h" #include <Qtgui> #include <QtWidgets> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { QLabel *label = new QLabel(tr("Hello World.")); setCentralWidget(label); } MainWindow::~MainWindow() { } となっています。 これをビルドして、Qt Creatorから実行するとウィンドウが表示されます。 しかし、単独で(ダブルクリックで)実行しようとすると 「コンピューターにQt5Cored.dllがないため、プログラムを開始できません。・・・」 というシステムエラーが表示され、実行できません。 これ以外に、mingwとmake を使って別のサンプルソースをコンパイルしても同様のエラーが出てきます。 実行ファイルと同じディレクトリにQt5Widgets.dll、Qt5Core.dll、Qt5Gui.dllの3つのDLLをコピーすると、実行できます。 しかし、いちいちDLLを要請するプログラム構成は好きでないのと、同名のライブラリlibQt5Widgets.a、libQt5Core.a、libQt5Gui.aがあることから、できれば静的にリンクしたいと思っています。 静的にリンクするために以下の4つの方法を試してみましたが、ことごとく失敗しています。 方法1 ライブラリを指定してリンク g++ -static -O0 -g -o Qt_test.exe Qt_test.obj -lmingw32 -LC:\Qt\5.11.0\mingw53_32\lib -lQt5Widgets -lQt5Core -lQt5Gui -lqtmain -LC:\utils\my_sql\my_sql\lib -LC:\utils\postgresql\pgsql\lib -lshell32 のような書式で、3つのライブラリの順番を入れかえて6パターン試しましたが、DLLエラーは変わりません。 方法2 ライブラリをld.exeでまとめたオブジェクトファイルを作ってリンク 「GNUソフトウェアプログラミング」という本の112ページにリンカ「ld」のオプションについての記述があり、オブジェクトファイルとライブラリ同士をリンクする方法が紹介されていたので試してみましたが、未解決の参照がない?のか、20バイトのファイルが出力されただけでした。 ld -static -r -o qtobj.o C:\Qt\5.11.0\mingw53_32\lib\libQt5Gui.a C:\Qt\5.11.0\mingw53_32\lib\libQt5Widgets.a C:\Qt\5.11.0\mingw53_32\lib\libQt5Core.a ld -static -r -o qtobj.o -LC:\Qt\5.11.0\mingw53_32\lib -lQt5Gui -lQt5Widgets -lQt5Core 方法3 arでオブジェクトファイルを作る ar rs qto2.a C:\Qt\5.11.0\mingw53_32\lib\libQt5Gui.a C:\Qt\5.11.0\mingw53_32\lib\libQt5Widgets.a C:\Qt\5.11.0\mingw53_32\lib\libQt5Core.a でライブラリをまとめたファイルは作れるのですが、コンパイルするとリンク時に qto2.a: error adding symbols: Archive has no index; run ranlib to add one となり、うまくいきません。 方法4 Qt creator で静的リンク Qt Creatorで「ライブラリの追加」を行うと、「HelloWrold.pro」に以下の行が加わり、リンクできそうなのですが、実行時にやはりDLLを要求されます。 LIBS += -LC:/Qt/5.11.0/mingw53_32/lib/ -lQt5Core 結局は、Qtで静的なリンクを行う方法が知りたいのです。 ご助言をお願いいたします。 環境は、Win7、Mingw、QtはMingwパッケージオプションを付けてインストールしており、 「C:\Qt\5.11.0\mingw53_32\lib\libQt5Core.a」 「C:\Qt\5.11.0\mingw53_32\include」 「C:\Qt\5.11.0\mingw53_32\bin\Qt5Core.dll」 があり、中にDLLもライブラリもあります。 よろしくお願いします。

  • 共有ライブラリへのパス指定の方法

    共有ライブラリへのパス指定の方法について教えて下さい。 環境は TurboLinux / C言語です lib_k.sl という共有ライブラリがあります。 【開発環境】  /hhn --- lib -(ここにlib_k.slがある)     |     -- src - ・・・(ここにプログラムのソースファイルがある) 【実行環境】  /ppc --- lib -(ここにlib_k.slを置く)     |     -- ld -(ここにプログラムのロードモジュールを置く) 開発プログラムのメイクファイルに、  /hhn/lib/lib_k.sl と書いてリンクさせています。すると、実行環境でも  /hhn/lib/lib_k.sl にリンクしようとしに行っているようです。 実行環境で /ppc/lib/lib_k.sl にリンクするには、どのようにすればよいのでしょうか? Cプログラミングはずっとやっていますが、共有ライブラリは使用したことが有りません。 ご教授お願いします。

  • VC++でビルド時の、リンク警告 LNK4006、LNK4221 を消したい

    こんにちは。 先週から仕事で Visual Stadio 2005 を使用して、C言語 でプログラムを書いています。 コードをビルドする際、ライブラリ作成時に以下の警告がでます。 1>Dynamic_02.lib(Dynamic_02.dll) : warning LNK4006: __NULL_IMPORT_DESCRIPTOR は Dynamic_01.lib(Dynamic_01.dll) で定義されています。2 つ目以降の定義は無視されます。 1>Dynamic_02.lib(Dynamic_02.dll) : warning LNK4221: パブリック シンボルが見つかりませんでした。アーカイブ メンバにアクセスできません。 これらの警告を消す方法はないですか? 以下は手順の詳細です。 1. 動的リンクライブラリ、Dynamic_01.dll を作成した。 同時にインポートライブラリ Dynamic_01.lib が作成される。 2. 動的リンクライブラリ、Dynamic_02.dll を作成した。 同時にインポートライブラリ Dynamic_02.lib が作成される。 3. Dynamic_01.dll と Dynamic_02.dll の両方の関数を使用する、 静的リンクライブラリ、Static_01.lib の作成を試みた。 追加の依存関係に Dynamic_01.lib と Dynamic_02.lib を指定し、 Static_01.lib をビルドすると、上記の警告が表示される。

  • ライブラリ??

    VCをつかってコーディングしています。 C言語仕様のネットワークプログラミングです。 socketをつくりデータのやり取りをするのですが gethostbyname()という関数が動作しません。 ちゃんとコンパイルもビルドもとおります。 ライブラリもwsock32.libやws2_32.libをリンクしています。 なにが原因なのかわかりません。 WINDOWSがまずいのでしょうか? 宜しくお願いします。

  • ダイナミックリンクライブラリ 実行 失敗

    「ダイナミックリンクライブラリ(DLL)初期化ルーチンの実行失敗」って、何が原因でしょうか?

  • ライブラリファイルのリンク (リリースバージョン時)

    VisualC++ 2005 Express Editionでライブラリファイル(.lib)をリリースバージョンでビルトし、違うプログラム(デバックバージョン)でライブラリファイルをリンクしたとき 1>コンパイルしています... 1>main.c 1>リンクしています... 1>CheckMemory.lib(check_memory.obj) : MSIL .netmodule または /GL を伴ってコンパイルされたモジュールが見つかりました。/LTCG を使用して再開始してください。リンカのパフォーマンスを向上させるためには、コマンドラインに /LTCG を追加してください。 1>LINK : warning LNK4075: /INCREMENTAL は /LTCG の指定によって無視されます。 1>LINK : warning LNK4098: defaultlib 'MSVCRT' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。 と出るのですが、これはどうゆうことなのでしょうか? 分かる方いらっしゃいますか?お願いします。 ちなみにライブラリファイルは簡易メモリチェックプロブラムでデバック時のみ使用したいと考えているプログラムです。 使用言語はc言語です。 文章下手ですみません^^;

  • ライブラリのリンクについて。

    ふと、疑問に思ったので質問させてもらいます。 C言語などでプログラムを作る時、ライブラリをリンクさせて使うと思いますが、その場合プログラムを実行させた場合メモリー上ではどうなるのか教えた貰いたいです。 例えばprintf関数を使う場合その命令そのものがプログラムに組み込まれてメモリーに読み込まれているのかということです。 前にどこかで読んだ記憶があるのですが、いろいろなところから呼び出される標準的なものはシステムで一箇所にありそれを使うなどということがあったような無かったような記憶があやふやですが見た覚えがあるので気になってしまいました。 あとライブラリなどから一つだけ関数を使う場合、使わない他の関数などもメモリーに読み込まれていたりするのでしょうか? よく使う自分で作った関数を一つのファイルにまとめ、それを定義したヘッダーファイルをincludeした場合も同様で使わないほかの関数はどうなるのでしょうか?

  • 複数のライブラリをリンクするときに構造体が衝突する

    C++,開発環境はVisual Studio Professional 2013です, ライブラリ1にxy座標の構造体 struct point { int x; int y; }; を定義しています. ライブラリ2にも全く同じ構造体を定義しています. ここで,あるプロジェクトからこれら2つのライブラリをリンクしようとしたら, error C2011: 'point' : 'struct' 型の再定義 というコンパイルエラーが出ます. ライブラリ1とライブラリ2にpoint構造体が記述された共通用のヘッダを参照させるという方法をとれば解決できるのでしょうが,この方法以外でこのエラーをなんとか回避する方法はないでしょうか. 構造体宣言は只の宣言であって実体をもたないため,中身が同じであればいくら記述が重複しても問題はないと聞いたことがあったので大丈夫だと思っていました. また,ライブラリ1とライブラリ2のpoint構造体の名前それぞれpoint1,point2にするなど違うものにするという方法でも回避できるのでしょうが,下記のメインコード内でコメントアウトされている部分のように,構造体の中身が全く同じなので互換性を持たせられるようにしたいのです. ちなみに,ライブラリ1,2はコンソールアプリケーション・空のプロジェクトで作成したあと,ソリューションのプロパティで「構成の種類」を「スタティックライブラリ(.lib)」にするという手順で作成しています. 以下,簡略コード ====ライブラリ1==== ----lib1.h---- #ifndef _H1_ #define _H1_ struct point { int x; int y; }; void print_lib1(struct point p); #endif ----lib1.cpp---- #include "lib1.h" #include <iostream> void print_lib1(struct point p) { std::cout << "lib1 : " << p.x << ", " << p.y << std::endl; } =====ライブラリ2====== ----lib2.h---- #ifndef _H2_ #define _H2_ struct point { int x; int y; }; void print_lib2(struct point p); #endif ----lib2.cpp---- #include "lib2.h" #include <iostream> void print_lib2(struct point p) { std::cout << "lib2 : " << p.x << ", " << p.y << std::endl; } ===メインコード=== ----main.cpp---- #include "../../lib1/lib1/lib1.h" #include "../../lib2/lib2/lib2.h" int main(void) { struct point val; val.x = 2; val.y = 3; print_lib1(val); //print_lib2(val); }

専門家に質問してみよう