가져 오기 라이브러리는 어떻게 작동합니까? 세부? 링크 용이라고 충분히 들었습니다. 그래서 내

나는 이것이 괴짜들에게 아주 기본적인 것처럼 보일 수 있다는 것을 알고 있습니다. 그러나 나는 그것을 명확하게하고 싶다.

Win32 DLL을 사용하려면 일반적으로 LoadLibrary () 및 GetProcAdderss ()와 같은 API를 호출합니다. 하지만 최근에는 DirectX9로 개발 중이며 d3d9.lib , d3dx9.lib 등의 파일 을 추가해야 합니다.

LIB는 정적 링크 용이고 DLL은 동적 링크 용이라고 충분히 들었습니다.

그래서 내 현재 이해는 LIB가 메서드의 구현을 포함하고 최종 EXE 파일의 일부로 링크 타임에 정적으로 링크된다는 것입니다. DLL은 런타임에 동적으로로드되며 최종 EXE 파일의 일부가 아닙니다.

그러나 때로는 DLL 파일 과 함께 제공 되는 일부 LIB 파일 있으므로 다음과 같습니다.

  • 이 LIB 파일은 무엇입니까?
  • 그들이 의미하는 바를 어떻게 성취합니까?
  • 이러한 LIB 파일의 내부를 검사 할 수있는 도구가 있습니까?

업데이트 1

wikipedia를 확인한 후 이러한 LIB 파일이 import library 라는 것을 기억합니다 . 하지만 주 응용 프로그램과 DLL이 동적으로로드되는 방식이 궁금합니다.

업데이트 2

RBerteig가 말했듯이 DLL로 태어난 LIB 파일에는 일부 스텁 코드가 있습니다. 따라서 호출 순서는 다음과 같아야합니다.

내 주 응용 프로그램-> LIB의 스텁-> 실제 대상 DLL

그렇다면 이러한 LIB에는 어떤 정보가 포함되어야합니까? 다음을 생각할 수 있습니다.

  • LIB 파일은 해당 DLL의 전체 경로를 포함해야합니다. 따라서 DLL은 런타임에 의해로드 될 수 있습니다.
  • 각 DLL 내보내기 방법의 진입 점에 대한 상대 주소 (또는 파일 오프셋?)는 스텁에 인코딩되어야합니다. 따라서 올바른 점프 / 메소드 호출을 할 수 있습니다.

내가 맞아? 뭔가 더 있나요?

BTW : 가져 오기 라이브러리를 검사 할 수있는 도구가 있습니까? 내가 볼 수 있다면 더 이상 의심이 없을 것입니다.



답변

DLL 파일에 대한 링크 는 컴파일 링크 타임에 암시 적으로 또는 런타임에 명시 적으로 발생할 수 있습니다 . 어느 쪽이든 DLL은 프로세스 메모리 공간에로드되고 내 보낸 모든 진입 점을 응용 프로그램에서 사용할 수 있습니다.

런타임에 명시 적으로 사용하는 경우, 사용 LoadLibrary()하고 GetProcAddress()수동으로 당신이 호출 할 필요가 함수에 대한 포인터를 DLL을로드하고 얻을.

프로그램이 빌드 될 때 암시 적으로 링크 된 경우 프로그램에서 사용하는 각 DLL 내보내기에 대한 스텁은 가져 오기 라이브러리에서 프로그램에 링크되고 해당 스텁은 프로세스가 시작될 때 EXE 및 DLL로로드 될 때 업데이트됩니다. (예, 여기서 조금 이상 단순화했습니다 …)

이러한 스텁은 어딘가에서 가져와야 하며 Microsoft 도구 체인에서 가져 오기 라이브러리 라는 특수한 형식의 .LIB 파일에서 가져옵니다 . 필요한 .LIB는 일반적으로 DLL과 동시에 빌드되며 DLL에서 내 보낸 각 함수에 대한 스텁을 포함합니다.

혼란스럽게도 동일한 라이브러리의 정적 버전도 .LIB 파일로 제공됩니다. DLL에 대한 가져 오기 라이브러리 인 LIB가 일반적으로 일치하는 정적 LIB보다 더 작다는 점 (종종 훨씬 더 작음)을 제외하고 구분하는 사소한 방법은 없습니다.

GCC 도구 모음을 사용하는 경우 우연히 DLL과 일치하는 가져 오기 라이브러리가 실제로 필요하지 않습니다. Windows로 포팅 된 Gnu 링커 버전은 DLL을 직접 이해하고 필요한 대부분의 스텁을 즉석에서 합성 할 수 있습니다.

최신 정보

모든 너트와 볼트가 실제로 어디에 있는지 그리고 실제로 무슨 일이 일어나고 있는지 알기에 저항 할 수 없다면 MSDN에는 항상 도움이 될 무언가가 있습니다. Matt Pietrek의 기사 An In-Depth Look into the Win32 Portable Executable File Format 은 EXE 파일의 형식과로드 및 실행 방법에 대한 매우 완벽한 개요입니다. 원래 MSDN Magazine ca에 게재 된 이후로 .NET 등을 포함하도록 업데이트되었습니다. 2002.

또한 프로그램에서 사용하는 DLL을 정확히 파악하는 방법을 아는 것도 도움이 될 수 있습니다. 이를위한 도구는 Dependency Walker (일명 dependent.exe)입니다. 이 버전은 Visual Studio에 포함되어 있지만 최신 버전은 작성자가 http://www.dependencywalker.com/ 에서 구할 수 있습니다 . 링크 타임에 지정된 모든 DLL (초기로드 및 지연로드)을 식별 할 수 있으며 프로그램을 실행하고 런타임에로드하는 추가 DLL을 감시 할 수도 있습니다.

업데이트 2

다시 읽기에 대해 명확히하고 MSDN과의 일관성을 위해 암시 적명시 적 링크 라는 용어를 사용하기 위해 이전 텍스트의 일부를 다시 작성했습니다 .

따라서 라이브러리 함수를 프로그램에서 사용할 수있는 세 가지 방법이 있습니다. 분명한 후속 질문은 “어떻게 어떤 방법을 선택합니까?”입니다.

정적 연결은 프로그램 자체의 대부분이 연결되는 방식입니다. 모든 개체 파일이 나열되고 링커에 의해 EXE 파일로 함께 수집됩니다. 그 과정에서 링커는 모듈이 서로의 함수를 호출 할 수 있도록 전역 심볼에 대한 참조를 수정하는 것과 같은 사소한 작업을 처리합니다. 라이브러리는 정적으로 링크 될 수도 있습니다. 라이브러리를 구성하는 개체 파일은 링커가 필요한 기호를 포함하는 모듈을 검색하는 .LIB 파일의 라이브러리 관리자에 의해 함께 수집됩니다. 정적 링크의 한 가지 효과는 프로그램에서 사용하는 라이브러리의 모듈 만 링크된다는 것입니다. 다른 모듈은 무시됩니다. 예를 들어, 기존 C 수학 라이브러리에는 많은 삼각 함수가 포함되어 있습니다. 그러나 당신이 그것에 대해 링크하고 사용한다면cos(), 당신의 코드의 사본을 결국하지 않습니다 sin()또는 tan()당신은 또한 그 기능을 호출하지 않는 한. 풍부한 기능 세트가있는 대형 라이브러리의 경우 모듈을 선택적으로 포함하는 것이 중요합니다. 임베디드 시스템과 같은 많은 플랫폼에서 라이브러리에서 사용할 수있는 총 코드 크기는 장치에 실행 파일을 저장하는 데 사용할 수있는 공간에 비해 클 수 있습니다. 선택적으로 포함하지 않으면 해당 플랫폼을위한 프로그램 구축 세부 사항을 관리하기가 더 어려울 것입니다.

그러나 실행중인 모든 프로그램에 동일한 라이브러리 의 사본이 있으면 일반적으로 많은 프로세스를 실행하는 시스템에 부담이됩니다. 올바른 종류의 가상 메모리 시스템을 사용하면 동일한 콘텐츠를 가진 메모리 페이지가 시스템에 한 번만 있으면 여러 프로세스에서 사용할 수 있습니다. 이렇게하면 코드가 포함 된 페이지가 가능한 한 많은 다른 실행중인 프로세스에서 일부 페이지와 동일 할 가능성이 높아집니다. 그러나 프로그램이 런타임 라이브러리에 정적으로 링크되면 각기 다른 위치에서 메모리 맵을 처리하는 각기 다른 조합의 기능을 갖게되며, 그 자체로 프로그램이 아닌 경우 공유 가능한 코드 페이지가 많지 않습니다. 프로세스 이상에서 실행됩니다. 따라서 DLL의 아이디어는 또 다른 주요 이점을 얻었습니다.

라이브러리 용 DLL에는 모든 클라이언트 프로그램에서 사용할 수있는 모든 기능이 포함되어 있습니다. 많은 프로그램이 해당 DLL을로드하면 모두 해당 코드 페이지를 공유 할 수 있습니다. 모두가 이깁니다. (글쎄, DLL을 새 버전으로 업데이트하기 전까지는이 이야기의 일부가 아닙니다. Google DLL Hell은 이야기의 측면에 있습니다.)

따라서 새 프로젝트를 계획 할 때 가장 먼저 선택해야하는 것은 동적 연결과 정적 연결 사이입니다. 정적 연결을 사용하면 설치할 파일이 줄어들고 사용하는 DLL을 제 3자가 업데이트하지 않아도됩니다. 그러나 프로그램은 더 크고 Windows 에코 시스템의 좋은 시민이 아닙니다. 동적 연결을 사용하면 설치할 파일이 더 많아지고 사용하는 DLL을 타사에서 업데이트하는 데 문제가있을 수 있지만 일반적으로 시스템의 다른 프로세스에 더 친숙합니다.

DLL의 큰 장점은 주 프로그램을 다시 컴파일하거나 다시 연결하지 않고도로드하고 사용할 수 있다는 것입니다. 이를 통해 타사 라이브러리 공급자 (예 : Microsoft 및 C 런타임)가 라이브러리의 버그를 수정하고 배포 할 수 있습니다. 최종 사용자가 업데이트 된 DLL을 설치하면 해당 DLL을 사용하는 모든 프로그램에서 해당 버그 수정의 이점을 즉시 얻습니다. (일을 깨뜨리지 않는 한. DLL Hell을 참조하십시오.)

다른 장점은 암시 적 로딩과 명시 적 로딩의 차이에서 비롯됩니다. 추가로 명시 적로드 작업을 수행하면 프로그램이 작성되고 게시 될 때 DLL이 존재하지 않았을 수 있습니다. 이를 통해 예를 들어 플러그인을 검색하고로드 할 수있는 확장 메커니즘을 사용할 수 있습니다.


답변

이러한 .LIB 가져 오기 라이브러리 파일은 Linker->Input->Additional Dependencies가져 오기 라이브러리 .LIB 파일에서 제공하는 링크 타임에 추가 정보가 필요한 dll을 빌드 할 때 다음 프로젝트 속성에서 사용됩니다 . 링커 오류가 발생하지 않도록 아래 예제에서 lib 파일을 통해 dll의 A, B, C 및 D를 참조해야합니다. (링커가 이러한 파일을 찾으려면 배포 경로를 포함해야 할 수도 있습니다. Linker->General->Additional Library Directories그렇지 않으면 제공된 lib 파일을 찾을 수 없다는 빌드 오류가 발생합니다.)

링커-> 입력-> 추가 종속성

솔루션이 모든 동적 라이브러리를 빌드하는 경우 대신 Common Properties->Framework and References대화 상자 아래에 노출 된 참조 플래그에 의존하여이 명시적인 종속성 사양을 피할 수있었습니다 . 이러한 플래그는 * .lib 파일을 사용하여 사용자를 대신하여 자동으로 링크를 수행하는 것으로 나타납니다.
프레임 워크 및 참조

그러나 이것은 구성이나 플랫폼에 특정한 것이 아닌 공통 속성을 말합니다 . 애플리케이션에서와 같이 혼합 빌드 시나리오를 지원해야하는 경우 정적 빌드를 렌더링하는 빌드 구성과 동적 라이브러리로 배포 된 어셈블리 하위 집합의 제한된 빌드를 빌드하는 특수 구성이있었습니다. 다양한 경우에 true로 설정된 Use Library Dependency InputsLink Library Dependencies플래그를 사용하여 빌드 할 항목을 얻고 나중에 단순화하기 위해 실현했지만 정적 빌드에 내 코드를 도입 할 때 많은 링커 경고를 도입했고 정적 빌드의 경우 빌드가 엄청나게 느 렸습니다. 나는 이런 종류의 경고를 많이 소개했다.

warning LNK4006: "bool __cdecl XXX::YYY() already defined in CoreLibrary.lib(JSource.obj); second definition ignored  D.lib(JSource.obj)

그리고 Additional Dependencies동적 빌드에 대한 링커를 만족시키기 위해 수동 사양을 사용하여 작업 속도를 늦추는 공통 속성을 사용하지 않음으로써 정적 빌더를 행복하게 유지했습니다. 동적 하위 집합 빌드를 배포 할 때 이러한 lib 파일은 런타임이 아닌 링크 타임에만 사용되므로 dll 파일 만 배포합니다.


답변

라이브러리에는 정적, 공유 및 동적으로로드 된 라이브러리의 세 가지 종류가 있습니다.

정적 라이브러리는 연결 단계에서 코드와 연결되므로 공유 라이브러리 파일에서 찾을 스텁 (기호) 만있는 공유 라이브러리와 달리 실제로 실행 파일에 있습니다. 주 함수가 호출됩니다.

동적으로로드 된 라이브러리는 작성한 코드에 의해 필요할 때로드된다는 점을 제외하면 공유 라이브러리와 매우 유사합니다.


답변


답변