合計 昨日 今日

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

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: さまよい
[URL]
Date: 2018年1月13日(土) 21:27
No: 1
(OFFLINE)

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

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

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

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

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

宜しくお願い致します

Name: かずま
[URL]
Date: 2018年1月14日(日) 00:41
No: 2
(OFFLINE)

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

さまよい さんが書きました: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) を書かなくても構いません。
コード[Text]: 全て選択
1
C:\tmp\DLL>cl /LD sum.c /link /EXPORT:sum

エクスポートする関数名がたくさんあるときは、
.defファイルに書いて、それを指定することもできます。

Name: あたっしゅ
[URL]
中級者(10,959 ポイント)
Date: 2018年1月14日(日) 07:04
No: 3
(OFFLINE)

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

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

Name: さまよい
[URL]
Date: 2018年1月14日(日) 10:24
No: 4
(OFFLINE)

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

かずま 様

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

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

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

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

Name: かずま
[URL]
Date: 2018年1月14日(日) 11:40
No: 5
(OFFLINE)

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

さまよい さんが書きました: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 を作成する環境をお持ちですか?
最初の回答の例を自分で試してみましたか?

Name: さまよい
[URL]
Date: 2018年1月14日(日) 17:45
No: 6
(OFFLINE)

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

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

>>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」とリンクできず、リンクエラーが発生するのではと思いますが?
この辺ご説明頂ければ幸せです。

Name: かずま
[URL]
Date: 2018年1月15日(月) 18:06
No: 7
(OFFLINE)

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

さまよい さんが書きました:どうもLinux系のほうがシンプルな印象ですけれども、
ただLinux系の場合*.so(dll)を生成するために補助的にlibのようなファイルを生成しないのは逆に不思議に思います。
DLLの中の関数に関する情報ファイル(eg., まがいのLIB)を生成しなければ、
DLL関数を利用する側は「まがいのLIB」とリンクできず、リンクエラーが発生するのではと思いますが?

Linux では、実行ファイルを生成するときに .soファイルを指定
しますから、リンカは何でもできるはずです。
呼び出し元には、静的リンクの関数を呼び出すようにみせて、
.soファイル内の関数を呼び出すような「つなぎの部分」を
生成することは可能です。

Name: さまよい
[URL]
Date: 2018年1月16日(火) 22:50
No: 8
(OFFLINE)

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

[解決!]

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

Name: かずま
[URL]
Date: 2018年1月17日(水) 21:59
No: 9
(OFFLINE)

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

つなぎの部分を私の妄想で作ってみました。
コード[C]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#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 とすると、
内部で次のような手順でリンクを行えばよいでしょう。

コード[Text]: 全て選択
1
2
3
gcc -c -o main.o main.c
gcc -c -o libsum.o libsum.c
gcc -o main main.o libsum.o -ldl


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[18人]