「shared library」とDLL----追加質問

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
さまよい

「shared library」とDLL----追加質問

#1

投稿記事 by さまよい » 3ヶ月前

今晩は
「shared library」とDLLに関して追加質問させて下さい。
前回:
かずまさん書かれました:
>> DLL の場合、実行ファイルを生成する時に情報を与えることもできるし、与えないこともできます。

Q1:  どんな場合、実行ファイルを生成する時に情報を与えることが必要でしょうか。

Q2:  もし生成する時に情報を与えることが必要とすれば、DLLの意味がなくなり、「静的」になってしまったのでは?

Q3:  DLLを生成するために、どうしてMS流ではわざわざソースコードの中に「余計」な文「__declspec(dllexport)」を挿入しなければならないのでしょうか。
    「__declspec(dllexport)はアプリケーションロジックとは関係ないですね。
    DLLとしない場合、ソースコードをいじらなくてはならなくなります。非常に不合理なやりかた?

宜しくお願い致します

かずま

Re: 「shared library」とDLL----追加質問

#2

投稿記事 by かずま » 3ヶ月前

さまよい さんが書きました: Q1:  どんな場合、実行ファイルを生成する時に情報を与えることが必要でしょうか。
暗黙のリンクを行う場合です。すなわち、
プログラムで LoadLibrary を実行しない場合です。
これは説明済みです。
さまよい さんが書きました: Q2:  もし生成する時に情報を与えることが必要とすれば、DLLの意味がなくなり、「静的」になってしまったのでは?
sum.dll を作成するときにできた sum.lib は静的にリンク
されますが、これには関数 sum の入り口しか存在せず、
そこから sum.dll 内の関数 sum を呼び出します。
sum.lib をリンクした main.exe は関数 sum の本体を
持っていないから、サイズは小さくなります。
さまよい さんが書きました: Q3:  DLLを生成するために、どうしてMS流ではわざわざソースコードの中に「余計」な文「__declspec(dllexport)」を挿入しなければならないのでしょうか。
    「__declspec(dllexport)はアプリケーションロジックとは関係ないですね。
    DLLとしない場合、ソースコードをいじらなくてはならなくなります。非常に不合理なやりかた?
DLL を作成するとき、エクスポートする関数名をリンクオプション
で指定すれば、__declspec(dllexport) を書かなくても構いません。

コード: 全て選択

C:\tmp\DLL>cl /LD sum.c /link /EXPORT:sum
エクスポートする関数名がたくさんあるときは、
.defファイルに書いて、それを指定することもできます。

アバター
あたっしゅ
記事: 142
登録日時: 7年前
住所: 東京23区
連絡を取る:

Re: 「shared library」とDLL----追加質問

#3

投稿記事 by あたっしゅ » 3ヶ月前

 そんなに M$ が嫌いなら、Windows でプログラムしなきゃいいでしょ。
手提鞄あたっしゅ、[MrAtassyu]

さまよい

Re: 「shared library」とDLL----追加質問

#4

投稿記事 by さまよい » 3ヶ月前

かずま 様

丁寧なご教授本当にありがとうございます。

かなり分かったような感じですけれども、追加質問させて下さい。
Q1. DLLを生成するために、必ずLIBも同時に生成されますね(同名?)。
    これはLINUX系においても同じでしょうか。

Q2. 通常DLLに入れられた関数は当然「 エクスポート」のためだと思いますが、
なぜその名前を一つ一つ列挙しなければならないのでしょうか。
   エクスポートする関数名がたくさんあるときは.defファイルに指定することは便利ですが、
これはLINUX世界においても同じやり方でしょうか。

また宜しくお願い致します。

かずま

Re: 「shared library」とDLL----追加質問

#5

投稿記事 by かずま » 3ヶ月前

さまよい さんが書きました: Q1. DLLを生成するために、必ずLIBも同時に生成されますね(同名?)。
__declspec(dllexport) をソースに記述せず、かつ、DLL
生成時にリンクオプションの /EXPORT を指定しなかった
場合は、.libファイルは生成されません。ただし、生成
された .dllファイルは何もエクスポートしないので
使い道がありません。
さまよい さんが書きました:     これはLINUX系においても同じでしょうか。
Linux においては、説明済みです。
.soファイルを作成したとき、.aファイルは作成されません。
実行ファイル生成時に .soファイルを指定すると、
dlopen なしで、.dllファイル内の関数を呼び出せます。
さまよい さんが書きました: Q2. 通常DLLに入れられた関数は当然「 エクスポート」のためだと思いますが、
なぜその名前を一つ一つ列挙しなければならないのでしょうか。
DLL内部だけで使いたい関数があるかもしれません。
さまよい さんが書きました:    エクスポートする関数名がたくさんあるときは.defファイルに指定することは便利ですが、
これはLINUX世界においても同じやり方でしょうか。
Linux でエクスポートは聞いたことがありません。
static でない関数は全部呼び出し可能なんだと思いますが、
調べてみないと分かりません。

質問です。
Windows で DLL を作成する環境をお持ちですか?
Linux で shared library を作成する環境をお持ちですか?
最初の回答の例を自分で試してみましたか?

さまよい

Re: 「shared library」とDLL----追加質問

#6

投稿記事 by さまよい » 3ヶ月前

かずま 様
お世話になっております。
大変分かりやすくご解説頂き誠に有難うございます。

>>Windows で DLL を作成する環境をお持ちですか?
>>Linux で shared library を作成する環境をお持ちですか?

WindowsにするかLinuxにするか実は環境整備これからです。
ということはこれから開発しようとするAPPはC言語で実装した多量の実体(*.dllか *.so)をPythonでcallするのを想定しており、

こんな場合
WindowsとLinuxとどっちがdllの生成と動的にcallするのはより簡単かを調べています。
どうもLinux系のほうがシンプルな印象ですけれども、
ただLinux系の場合*.so(dll)を生成するために補助的にlibのようなファイルを生成しないのは逆に不思議に思います。
DLLの中の関数に関する情報ファイル(eg., まがいのLIB)を生成しなければ、
DLL関数を利用する側は「まがいのLIB」とリンクできず、リンクエラーが発生するのではと思いますが?
この辺ご説明頂ければ幸せです。

かずま

Re: 「shared library」とDLL----追加質問

#7

投稿記事 by かずま » 3ヶ月前

さまよい さんが書きました: どうもLinux系のほうがシンプルな印象ですけれども、
ただLinux系の場合*.so(dll)を生成するために補助的にlibのようなファイルを生成しないのは逆に不思議に思います。
DLLの中の関数に関する情報ファイル(eg., まがいのLIB)を生成しなければ、
DLL関数を利用する側は「まがいのLIB」とリンクできず、リンクエラーが発生するのではと思いますが?
Linux では、実行ファイルを生成するときに .soファイルを指定
しますから、リンカは何でもできるはずです。
呼び出し元には、静的リンクの関数を呼び出すようにみせて、
.soファイル内の関数を呼び出すような「つなぎの部分」を
生成することは可能です。

さまよい

Re: 「shared library」とDLL----追加質問

#8

投稿記事 by さまよい » 3ヶ月前

かずま 様
さすが! ありがとうございました。

かずま

Re: 「shared library」とDLL----追加質問

#9

投稿記事 by かずま » 3ヶ月前

つなぎの部分を私の妄想で作ってみました。

コード: 全て選択

#include <stdlib.h>
#include <dlfcn.h>

int sum(int n);
void sum1(void);
int sum2(char *s, const char *t);

struct FuncTable {
    void (*func)(void);
    const char *name;
};

struct FuncTable ft[3] = {
    { 0, "sum" },
    { 0, "sum1" },
    { 0, "sum2" },
};

void *so;

void set_ft(int i)
{
    if (!so) {
        so = dlopen("sum.so", RTLD_LAZY);
        if (!so) exit(1);
    }
    ft[i].func = dlsym(so, ft[i].name);
    if (!ft[i].func) exit(2);
}

int sum(int n)
{
    if (!ft[0].func) set_ft(0);
    return ((int (*)(int))ft[0].func)(n);
}

void sum1(void)
{
    if (!ft[1].func) set_ft(1);
    return ((void (*)(void))ft[1].func)();
}

int sum2(char *s, const char *t)
{
    if (!ft[2].func) set_ft(2);
    return ((int (*)(char *, const char *))ft[2].func)(s, t);
}
sum 1個だけではつまらないので、sum1、sum2 を追加してみました。

gcc -o main main.c sum.dll で実行ファイル生成しようとすると、
sum.dll があるため、 上記のような「つなぎの部分」を自動的に
作ります。sum.dll は、中に呼び出し可能な関数の情報を持っている
はずですから、このようなことができます。これを仮に libsum.c とすると、
内部で次のような手順でリンクを行えばよいでしょう。

コード: 全て選択

gcc -c -o main.o main.c
gcc -c -o libsum.o libsum.c
gcc -o main main.o libsum.o -ldl

返信

“C言語何でも質問掲示板” へ戻る