2009-12-10 3 views
8

호스트 응용 프로그램의 STL 컨테이너에 저장된 데이터에 액세스해야하는 DLL이 있습니다. C++에는 표준 ABI가없고 여러 컴파일러를 지원하기 때문에 응용 프로그램과 DLL 간의 인터페이스는 기본적으로 평범한 데이터로 남아 있어야합니다.DLL 경계를 통해 STL 목록을 노출하는 방법은 무엇입니까?

벡터의 경우 이것은 비교적 간단합니다. 이 contigious이 보장되기 때문에 당신은 단순히 벡터의 메모리 블록을 반환 할 수 있습니다

// To return vector<int> data 
virtual void GetVectorData(const int*& ptr, size_t& count) const 
{ 
    if (!vec.empty()) 
     ptr = &(vec.front()); 

    count = vec.size(); 
} 

이제 DLL은 인터페이스를 통해 벡터의 데이터에 대한 안전한 읽기 전용 액세스 할 수 있습니다. DLL은 내용을 벡터 자체에 복사하기 위해이를 감쌀 수도 있습니다.

STL 목록 (및 deques)은 어떻게됩니까? DLL 경계를 통해 액세스를 허용하는 또 다른 직접적인 방법이 있습니까? 아니면 어떤 종류의 GetFirst()/GetNext() 인터페이스에 의존해야합니까? 많은 목록에 대해이 작업을 수행해야 할 수도 있으므로 벡터와 같은 간단한 솔루션을 갖는 것이 좋을 것입니다.

답변

7

아마도 "핸들"과 같은 것을 리스너/deque 반복기에 전달할 수 있습니까? 이러한 핸들 유형은 사용자에게 제공 할 헤더 파일에서 불투명하고 선언됩니다. 내부적으로 핸들 값을 list/deque iterator에 매핑해야합니다. 당신은 DLL을 사이에 STL 객체를 통과하고 각 STL 유형의 인스턴스 위치를주의 경우 다른 컴파일러를 지원할 수

ListHandle lhi = GetListDataBegin(); 
const ListHandle lhe = GetListDataEnd(); 

while (lhi != lhe) 
{ 
    int value = GetListItem(lhi); 
    ... 
    lhi = GetNextListItem(lhi); 
} 
1

응용 프로그램 과 DLL 사이의 인터페이스는 기본적으로 일반 오래된 데이터가 남아있다.

반드시 그렇지는 않습니다. 동일한 컴파일러 버전이 사용되는지 확인해야합니다. 또한 STL 개체의 레이아웃에 영향을주는 빌드 설정은 dll과 응용 프로그램간에 완전히 동일합니다.

dll을 야생으로 배포하려면 dll 경계를 넘어 STL을 노출하는 것이 좋습니다. 그러나 모든 것이 사용자의 통제하에 있고 순전히 내부 (또는 타사 빌드 설정/컴파일러를 엄격하게 적용 할 수있는 경우)라면 괜찮습니다.

+0

모든 컴파일 설정이 동일하다면 빠져 나갈 수 있습니다. 하지만 이것은 플러그인 아키텍처를위한 것이며 다른 컴파일러를 지원하고 싶습니다. 나는 이것을 명확히하기 위해 질문을 편집했다. – AshleysBrain

+0

필자는 이것에 동의하지만 어쩌면 레이아웃뿐 아니라 새로운 컴파일러와 같은 메소드의 구현이 일치하도록 코드를 컴파일해야합니다. –

+0

빌드 설정/컴파일러 버전을 엄격하게 적용하고 모든 것이 사용자의 통제하에 있다면 정적 라이브러리를 사용하고 모든 것을 하나의 실행 파일로 연결하는 것보다 DLL의 장점은 무엇입니까? –

10

: 기본적으로, 사용자는 같은 코드를 작성합니다. 지능적인 "DLLEXPORT"매크로가 필요합니다. 다음 세트를 사용하여 VC와 gcc를 성공적으로 지원합니다.

#ifdef WIN32 
#ifdef MYDLLLIB_EXPORTS  // DLL export macros 
#define MYDLLLIB_API __declspec(dllexport) 
#define MYDLLLIB_TEMPLATE 
#else 
#define MYDLLLIB_API __declspec(dllimport) 
#define MYDLLLIB_TEMPLATE extern 
#endif 
#else      // Not windows --- probably *nix/bsd 
#define MYDLLLIB_API 
#ifdef MYDLLLIB_EXPORTS 
#define MYDLLLIB_TEMPLATE 
#else 
#define MYDLLLIB_TEMPLATE extern 
#endif 
#endif // WIN32 

DLL을 컴파일 할 때 MYDLLLIB_EXPORTS를 정의하십시오. DLL을 당신은 다음이 표시됩니다 (정의 MYDLLLIB_EXPORTS이없는) 예를 들어, 목록 또는 DLL의 문자열

MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::vector<std::string>; 
MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::list<std::string>; 

소비자의 벡터에 대한 사용하고자하는 각 STL과 유형을 인스턴스화 할 수

extern template class __declspec(dllimport) std::vector<std::string>; 

및 자신의 인스턴스를 만드는 대신 DLL에서 내 보낸 이진 코드를 사용하십시오.

+0

그것은 매우 흥미로운 해결책입니다 - 표준을 위해 동일한 작업을 수행해야합니까 :: :: iterator and std :: list :: iterator? 호스트 EXE에서 DLL을 사용하는 STL 클래스와 동일한 방법입니까? – AshleysBrain

+0

특정 stl 컨테이너 클래스를 인스턴스화 할 때 컨테이너 클래스 내의 모든 클래스에 대한 코드를 얻을 수 있기 때문에 반복기를 인스턴스화 할 필요가 없습니다. 호스트 EXE에서 STL 클래스를 소비하는 것에 대해 모르겠다. 개인적으로 시도하지는 않았으므로이 메서드를 따르려면 간단한 테스트로 약간의 실험을해야한다. – mcdave

+2

MSDN 문서 : http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q168958 – k06a

관련 문제