문제

이 질문은 관련이 있습니다 "VS 버전에서 일관된 DLL 바이너리를 만드는 방법?"

  • VC6과 함께 구축 된 응용 프로그램과 DLL이 있으며 VC9로 구축 된 새로운 응용 프로그램이 있습니다. VC9-App은 VC6과 함께 컴파일 된 DLL을 사용해야하며, 대부분 C ++로 작성됩니다.
  • C ++ LIB는 이름 장식/망설링 문제로 인해 문제가됩니다.
  • VC9로 모든 것을 컴파일하는 것은 현재 부작용이있는 것처럼 보이기 때문에 옵션이 아닙니다. 이것을 해결하는 데 시간이 많이 걸릴 것입니다.
  • C ++ 라이브러리를 수정할 수 있지만 VC6으로 컴파일해야합니다.
  • C ++ LIB는 본질적으로 다른 C 라이브러리의 OO-Wrapper입니다. VC9-App은 일부 정적 기능과 비 정적 기능을 사용합니다.

정적 함수는

// Header file
class DLL_API Foo
{
    int init();
}

extern "C"
{
    int DLL_API Foo_init();
}

// Implementation file
int Foo_init()
{
    return Foo::init();
}

비 정적 방법으로는 쉽지 않습니다.

내가 이해하면서 Chris Becke 's COM과 같은 인터페이스를 사용하는 제안은 인터페이스 멤버 이름이 여전히 장식되어 다른 컴파일러로 생성 된 바이너리에서 접근 할 수 없기 때문에 도움이되지 않습니다. 내가 바로 거기있어?

유일한 솔루션은 핸들러를 객체에 사용하여 C 스타일 DLL 인터페이스를 작성하는 것입니다. 아니면 내가 뭔가 빠진 것입니까? 이 경우, 나는 래핑 된 C- 라이브러리를 직접 사용하는 데 더 적은 노력을 기울일 것이라고 생각합니다.

도움이 되었습니까?

해결책

인터페이스 멤버 이름이됩니다 ~ 아니다 장식하십시오 - 그들은 vtable에서 단지 오프셋입니다. 헤더 파일에서 인터페이스 (com "인터페이스"대신 C 구조물 사용)를 정의 할 수 있습니다.

struct IFoo {
    int Init() = 0;
};

그런 다음 망설없이 DLL에서 함수를 내보낼 수 있습니다.

class CFoo : public IFoo { /* ... */ };
extern "C" IFoo * __stdcall GetFoo() { return new CFoo(); }

호환 가능한 vtables를 생성하는 컴파일러를 사용하는 경우에는 제대로 작동합니다. Microsoft C ++는 DOS에 대해 MSVC6.1 이후 동일한 형식의 VTable을 생성했습니다. 여기서 vtable은 함수에 대한 간단한 포인터 목록입니다 (다중 상영 케이스에서 뭉개립니다). GNU C ++ (올바르게 기억하는 경우)는 기능 포인터 및 상대 오프셋으로 VTABLE를 생성합니다. 이것들은 서로 호환되지 않습니다.

다른 팁

호출 EXE와 다른 C ++ 컴파일러로 컴파일 된 DLL을 사용할 때 고려해야 할 가장 큰 문제는 메모리 할당 및 객체 수명입니다.

나는 당신이 이름 Mangling (및 Calling Convention)을 지나갈 수 있다고 가정합니다. 호환 가능한 Mangling이있는 컴파일러를 사용하는 경우 어렵지 않습니다 (VC6은 VS2008과 광범위하게 호환되는 것 같습니다). .

문제가 발생할 곳은 사용을 사용하는 무언가를 할당 할 때입니다. new (또는 malloc)) DLL에서, 그리고 당신은 이것을 발신자에게 반환합니다. 발신자 delete (또는 free)는 다른 힙에서 물체를 제거하려고 시도합니다. 이것은 끔찍하게 잘못 될 것입니다.

당신은 com 스타일을 할 수 있습니다 IFoo::Release 사물, 또는 a MyDllFree() 물건. 이 두 가지 모두 DLL로 다시 전화하기 때문에 올바른 구현을 사용합니다. delete (또는 free()), 그래서 그들은 올바른 개체를 삭제합니다.

또는 사용하는지 확인할 수 있습니다 LocalAlloc (예를 들어), EXE와 DLL이 동일한 힙을 사용하도록합니다.

글쎄요 Chris Becke의 제안 괜찮습니다. 나는 사용하지 않을 것이다 로저의 첫 번째 솔루션, 이름 만 인터페이스를 사용하고 그가 언급했듯이 추상 클래스 및 가상 방법의 호환되지 않는 컴파일러 처리 문제가 발생할 수 있습니다. Roger는 매력적인 COM과 일치하는 케이스를 가리 킵니다 그의 후속.

  1. 통증 지점 : COM 인터페이스 요청을하는 법을 배워야하고 IunkNown을 제대로 처리하여 최소 IunkNown : Addref 및 IunkNown : Release에 의존합니다. 인터페이스의 구현이 둘 이상의 인터페이스를 지원할 수 있거나 메소드가 인터페이스를 반환 할 수있는 경우 iunknown : QueryInterface와 편안하게해야 할 수도 있습니다.

  2. 주요 아이디어는 다음과 같습니다. 인터페이스의 구현을 사용하는 모든 프로그램 (그러나 구현하지 않음)은 인터페이스를 struct (c) 또는 c/c ++ 클래스 (vc ++)로 정의하는 공통 #include "*.h"파일을 사용합니다. 구조물 (비 VC ++이지만 C ++). *.h 파일은 C 언어 프로그램 또는 C ++ 언어 프로그램을 컴파일하는지 여부에 따라 자동으로 적절하게 조정합니다. *.h 파일을 사용하기 위해 그 부분에 대해 알 필요가 없습니다. *.h 파일이하는 일은 가상 멤버 함수를 갖춘 인터페이스 구조 또는 유형을 정의하는 것입니다 (이 접근법에서 데이터 구성원에 대한 직접적인 가시성은 없음).

  3. 헤더 파일은 사용되는 C ++ 컴파일러에 관계없이 C에 맞는 방식으로 COM 바이너리 표준을 존중하도록 구성됩니다. (Java Jni Polk는 이것을 알아 냈습니다.) 이것은 전적으로 기능 입력 포인터 (vtable)로 구성된 구조물이 그들 모두에 의해 메모리에 맵핑되는 한 모든 원점의 별도로 컴파일 된 모듈 사이에서 작동한다는 것을 의미합니다. (예를 들어 모든 x86 32 비트 또는 모든 x64 여야합니다).

  4. 어떤 종류의 래퍼 클래스를 통해 COM 인터페이스를 구현하는 DLL에서는 공장 진입 점만 필요합니다. 같은 것

    extern "c"hresult mkifooimplementation (void ** ppv);

HRESULT를 반환하고 (이에 대해서도 배워야 함) IFOO 인터페이스 포인터를 수신하기 위해 제공하는 위치에서 *PV를 반환합니다. (나는 으르렁 거리며 여기에 필요한 세부 사항이 더 신중합니다. 내 구문을 신뢰하지 마십시오) 이것에 사용하는 실제 함수 고정 관념은 *.h 파일에도 선언됩니다.

  1. 요점은 항상 노동되지 않은 외부 "C"인 공장 항목은 필요한 모든 래퍼 클래스 작성을 수행 한 다음 지정한 위치에 대한 IFOO 인터페이스 포인터를 제공한다는 것입니다. 이는 클래스 생성을위한 모든 메모리 관리 및 마무리를위한 모든 메모리 관리가 래퍼를 구축하는 DLL에서 발생 함을 의미합니다. 이 세부 사항을 처리 해야하는 유일한 곳입니다.

  2. 공장 기능에서 확인 결과를 얻을 때 인터페이스 포인터가 발행되었으며 이미 귀하를 위해 예약되었습니다 (내재 된 IFOO : AddRef 작업이 이미 전달 된 인터페이스 포인터를 대신하여 이미 수행되었습니다).

  3. 인터페이스를 완료하면 인터페이스의 IFOO : 릴리스 메소드에서 호출로 해제합니다. 공장 DLL에서 클래스와 인터페이스 지원을 중단하는 최종 릴리스 구현 (AddRef'd Copies를 더 많이 만든 경우)입니다. 공장 함수를 포함하는 DLL이 호출 코드와 동일한 라이브러리를 사용하는지 여부에 관계없이 일관된 동적 스토 러지 할당 및 인터페이스 뒤에서 릴리스에 대한 의존을 정확하게하는 것입니다.

  4. 항상 실패하더라도 iunkNown : QueryInterface (메소드 ifoo : QueryInterface)도 구현해야합니다. 더 많은 경험을 가지고 있기 때문에 Com Binary Interface 모델을 사용하는 데 더 정교한 경우 전체 QueryInterface 구현을 제공하는 법을 배울 수 있습니다.

이것은 아마도 너무 많은 정보이지만, DLL의 이종 구현에 대해 직면하고있는 많은 문제가 Com Binary 인터페이스의 정의에서 해결되며 모든 것이 필요하지 않더라도 그것이 작동하는 솔루션을 제공한다는 사실은 가치가 있습니다. 내 경험에 따르면, 일단 당신이 이것을 매달린 후에, 당신은 이것이 C ++ 및 C ++ Interop 상황에서 얼마나 강력한지를 잊지 않을 것입니다.

예제를 위해 상담해야 할 자원과 *.h 파일을 만들고 실제로 공유하려는 라이브러리의 공장 기능 랩퍼를 구현하기 위해 배워야 할 자원을 스케치하지 않았습니다. 더 깊이 파고 싶다면 Holler.

다양한 라이브러리에서 어떤 런 타임을 사용하고 있는지와 같이 고려해야 할 다른 것들이 있습니다. 공유가 없다면 괜찮지 만 언뜻보기에는 거의 보이지 않습니다.
Chris Becker의 제안은 매우 정확합니다. 실제 COM 인터페이스는 필요한 이진 호환성을 얻는 데 도움이 될 수 있습니다. 귀하의 마일리지가 다를 수 있습니다 :)

재미 있지 않아, 남자. 당신은 많은 좌절감을 느끼고 있습니다. 아마 이것을 주어야 할 것입니다.

유일한 솔루션은 핸들러를 객체에 사용하여 C 스타일 DLL 인터페이스를 작성하는 것입니다. 아니면 내가 뭔가 빠진 것입니까? 이 경우, 나는 래핑 된 C- 라이브러리를 직접 사용하는 데 더 적은 노력을 기울일 것이라고 생각합니다.

정말 가까운 모습. 행운을 빕니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top