Win32では、 A.dll と呼ばれる動的ライブラリを構築し、 B.lib と呼ばれる静的ライブラリにリンクし、実行可能ファイルも構築しましたC.exeと呼ばれ、 only はA.dllに依存します。
しかし今、 C.exe で foo を使用する場合は、 B.libでのみ定義されています。 、C.exeをB.libに対して再度リンクする必要があります。
問題は、 foo をB.libからA.dllに直接エクスポートできるかどうかです。 A.dllをビルドして、どうやって?
また、私はGCCを扱うときにそれがどうなるか知りたいです。
関数foo
は、DLL=
関数をオブジェクトファイルにコンパイルするときに、foo
を__declspec(dllexport)
属性で宣言します。たとえば、_foo.obj
_と宣言します。
_foo.obj
_をDLLにリンクします。
_foo.obj
_がDLLにリンクされる方法は問題ではありません。
DLLのリンケージで_foo.obj
_を明示的に指定する可能性があります。
多分あなたは_foo.obj
_を静的ライブラリの中に入れて、_foobar.lib
_と書いて、DLLのリンケージに関数foo
への参照が含まれているかもしれません次に、リンカは_foo.obj
_から_foobar.lib
_を抽出してDLLにリンクし、その参照を解決します。
_foo.obj
_が静的ライブラリから抽出されてリンクされている場合、リンケージは_foo.obj
_が名前でリンクされている場合とまったく同じです。静的ライブラリは、リンカがリンケージを実行するために必要なものを選択できるオブジェクトファイルのバッグです。リンケージが完了すると、生成されたプログラムまたはDLL=は静的ライブラリに依存しません。バッグにオブジェクトファイルが必要な場合は、ここでそれらを取得します。これは必要ありません。バッグ。
以下は、Windows用のGCC mingw-w64ツールチェーンを使用して、静的ライブラリ内からDLLでエクスポートされた関数をリンクする方法の図です。
_C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev0>echo off
Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.
C:\>cd develop\so\scrap
C:\develop\so\scrap>dir
Volume in drive C has no label.
Volume Serial Number is 16C7-F955
Directory of C:\develop\so\scrap
16/12/2017 17:50 <DIR> .
16/12/2017 17:50 <DIR> ..
16/12/2017 12:41 116 greeting.cpp
16/12/2017 12:42 99 greeting.h
16/12/2017 12:10 109 hello.cpp
16/12/2017 12:12 90 hello.h
16/12/2017 16:21 197 main.cpp
16/12/2017 12:25 117 niceday.cpp
16/12/2017 12:26 96 niceday.h
7 File(s) 824 bytes
2 Dir(s) 101,878,943,744 bytes free
_
hello.cpp
_#include "hello.h"
#include <iostream>
void hello()
{
std::cout << "Hello world!" << std::endl;
}
_
hello.h
_#ifndef HELLO_H
#define HELLO_H
extern __declspec(dllexport) void hello();
#endif
_
_hello.cpp
_をコンパイルします。
_C:\develop\so\scrap>g++ -Wall -c -o hello.obj hello.cpp
_
同様に:
niceday.cpp
_#include "niceday.h"
#include <iostream>
void niceday()
{
std::cout << "What a Nice day!" << std::endl;
}
_
niceday.h
_#ifndef NICEDAY_H
#define NICEDAY_H
extern __declspec(dllexport) void niceday();
#endif
_
_niceday.cpp
_をコンパイルします
_C:\develop\so\scrap>g++ -Wall -c -o niceday.obj niceday.cpp
_
次に、これら2つのオブジェクトファイルを静的ライブラリに配置します。 _libgreet.lib
_
_ar rcs libgreet.lib hello.obj niceday.obj
_
別のソースファイルとヘッダー:
greeting.cpp
_#include "greeting.h"
#include "hello.h"
#include "niceday.h"
void greeting()
{
hello();
niceday();
}
_
greeting.h
_#ifndef GREETING_H
#define GREETING_H
extern __declspec(dllexport) void greeting();
#endif
_
これもコンパイルします。
_g++ -Wall -c -o greeting.obj greeting.cpp
_
次に、_libgreeting.dll
_と静的ライブラリ_greeting.obj
_を使用して、DLL _libgreet.lib
_を作成します。
_C:\develop\so\scrap>g++ -shared -o libgreeting.dll greeting.obj libgreet.lib
_
ここにプログラムソースファイルがあります:
main.cpp
_#include "hello.h"
#include "niceday.h"
#include "greeting.h"
#include <iostream>
int main()
{
hello();
niceday();
std::cout << "I said..." << std::endl;
greeting();
return 0;
}
_
これもコンパイルします:
_C:\develop\so\scrap>g++ -Wall -c -o main.obj main.cpp
_
最後に、_main.obj
_と_libgreeting.dll
_をリンクしてプログラムを作成します。 のみと_libgreeting.dll
_。
_C:\develop\so\scrap>g++ -o prog main.obj libgreeting.dll
_
プログラムを実行します。
_C:\develop\so\scrap>prog
Hello world!
What a Nice day!
I said...
Hello world!
What a Nice day!
_
DLLでエクスポートされた3つの関数hello
、niceday
およびgreeting
が呼び出されます。 重要なことこれが発生するためには、それらすべてが__declspec(dllexport)
として宣言され、それらすべてが_libgreeting.dll
_にリンクされたということですsomehow 。たまたま、そのうちの2つ(hello
、niceday
)は静的ライブラリからリンクされ、もう1つ(greeting
)はオブジェクトファイルから直接リンクされました。これは関係ありません。
そして興味があれば...
Visual Studio 2017ツールチェーンで同じことを行う方法は次のとおりです。
_**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.4.3
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
C:\Users\mikek\source>cd C:\develop\so\scrap
C:\develop\so\scrap>dir
Volume in drive C has no label.
Volume Serial Number is 16C7-F955
Directory of C:\develop\so\scrap
16/12/2017 18:31 <DIR> .
16/12/2017 18:31 <DIR> ..
16/12/2017 12:41 116 greeting.cpp
16/12/2017 12:42 99 greeting.h
16/12/2017 12:10 109 hello.cpp
16/12/2017 12:12 90 hello.h
16/12/2017 16:21 197 main.cpp
16/12/2017 12:25 117 niceday.cpp
16/12/2017 12:26 96 niceday.h
7 File(s) 824 bytes
2 Dir(s) 101,877,473,280 bytes free
_
コンパイル_hello.cpp
_:
_C:\develop\so\scrap>cl /W4 /EHsc /c /Fohello.obj hello.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
hello.cpp
_
コンパイル_niceday.cpp
_:
_C:\develop\so\scrap>cl /W4 /EHsc /c /Foniceday.obj niceday.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
niceday.cpp
_
静的ライブラリを作成します。
_C:\develop\so\scrap>lib /out:libgreet.lib hello.obj niceday.obj
Microsoft (R) Library Manager Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
_
コンパイル_greeting.cpp
_:
_C:\develop\so\scrap>cl /W4 /EHsc /c /Fogreeting.obj greeting.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
greeting.cpp
_
リンク_libgreeting.dll
_:
_C:\develop\so\scrap>link /dll /out:libgreeting.dll greeting.obj libgreet.lib
Microsoft (R) Incremental Linker Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
Creating library libgreeting.lib and object libgreeting.exp
_
ここで、ご存じのとおり、Microsoftリンカーはインポートライブラリ _libgreeting.lib
_を作成します。これは、_libgreet.lib
_のリンクに使用される静的ライブラリ_libgreeting.dll
_と混同しないでください)プログラムまたは別のDLLに。
コンパイル_main.cpp
_:
_C:\develop\so\scrap>cl /W4 /EHsc /c /Fomain.obj main.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
main.cpp
_
プログラムをリンクします(_libgreeting.lib
_の代わりにインポートライブラリ_libgreeting.dll
_を使用):
_C:\develop\so\scrap>link /out:prog.exe main.obj libgreeting.lib
Microsoft (R) Incremental Linker Version 14.11.25547.0
Copyright (C) Microsoft Corporation. All rights reserved.
_
そして実行します:
_C:\develop\so\scrap>prog
Hello world!
What a Nice day!
I said...
Hello world!
What a Nice day!
_
後で
foo
が最初に__declspec(dllexport)
なしでコンパイルされ、B.libをビルドしたときにこのvoid foo()
のような宣言がある場合しかし、C.exeをビルドしたとき、fooの宣言を__declspec(dllexport) void foo()
に変更しました。問題は、私がまだ上記を実現できるかどうかです
原則として、ヘッダーファイルでfoo
の特定の宣言を使用してオブジェクトファイルをコンパイルし、次にchange _#include
_に続いてその宣言をコンパイルした場合、他のオブジェクトファイルの場合、2回目のコンパイルでコンパイラに嘘をついている可能性が高く、これらのオブジェクトファイルをいくつかのプログラムまたはDLLにリンクすると、悪いことが発生する可能性があります。
ただし、この場合は、問題を回避できます。上記の例では、まず_hello.cpp
_の宣言を使用して_hello.h
_をコンパイルできます。
_extern void hello(void);
_
後で_greeting.cpp
_をコンパイルするとき、その_#include
_ s _hello.h
_を宣言するときに、宣言を次のように変更できます。
_extern __declspec(dllexport) void hello(void);
_
_libgreeting.dll
_をリンクすると、hello
willがDLL_exportされるという結果になります。
__declspec(dllexport)
を使用した宣言は、使用しないものと矛盾するのではなく、改良されます。 _libgreeting.dll
_をリンクすると、リンカーは_hello.obj
_のhello
への非DLLエクスポート参照と_greeting.obj
_のDLLエクスポート参照を参照します。少なくとも1つのDLLでエクスポートされた参照を確認したため、シンボルをDLLでエクスポートします。
これがhackであることは間違いありません。