문제

First_Layer

VC ++ 6 서비스 팩 6에 Win32 DLL이 작성되었습니다. FirstLayer의 소스 코드에 액세스 할 수는 없지만 관리 코드에서 호출해야합니다. 문제는 Firstlayer가 std :: vector 및 std :: string을 많이 사용하고 이러한 유형을 C# 응용 프로그램으로 직접 마샬링하는 방법이 없다는 것입니다. 아래이 계층의 코드는이 DLL에서 찾을 수있는 내용의 예를 보여줍니다.

Second_layer

내가 생각할 수있는 솔루션은 먼저 VC ++ 6 서비스 팩으로 작성된 또 다른 Win32 DLL을 만드는 것입니다. Sec

Third_Layer

또한 두 번째 레이어의 래퍼로 VC ++ 2005 클래스 라이브러리를 만들었습니다. 이 래퍼는 관리되지 않는 2 학년을 관리 코드로 변환하는 모든 더러운 작업을 수행합니다. 이 레이어를 "Thirdlayer"라고합시다. 아래 그림과 같이이 레이어의 코드는 오류를 보여주기 위해 단순화되어 위에서 언급 한 변환을 수행하지 않습니다.

Fourth_Layer

무엇보다도, 나는 C#2005 콘솔 애플리케이션을 만들어 ThirdLayer를 호출했습니다. 이 C# 콘솔 응용 프로그램을 "Fourthlayer"라고합시다.

호출 시퀀스 요약

Fourthlayer (C#2005) -> ThirdLayer (VC ++ 2005) -> SecondLayer (VC ++ 6) -> FirstLayer (VC ++ 6)

런타임 오류

아래 코드 아래 코드는 오류없이 컴파일/빌드하지만 다음 런타임 오류가 발생합니다.

처리되지 않은 예외 : System.AccessViolationException : 보호 된 메모리를 읽거나 쓰려고 시도했습니다. 이것은 종종 다른 기억이 손상되었음을 나타냅니다. secondlayer.PassDatabackTocaller에서 (2 차 레이어 , stdVectorWrapper*)에서 sample.thirdlayer.passdatabacktocaller ()의 c : project in c : project on going projects test sample thirdlayer thirdlayer.cpp : fourthlayer.program.main (string [] args)의 22 행 C : 프로젝트 프로젝트 test test sample fourthlayer program.cs : 라인 14*

이 오류는 다른 운영 체제에서 Fourthlayer 응용 프로그램이 실행될 때 표시되지 않습니다. 예를 들어 Windows XP의 경우 오류가 없지만 Vista 및 Windows 7과 같은 다른 OS의 경우 오류가 나타납니다.

나는 이것을 일으키는 원인을 이해하지 못한다. 어떤 아이디어? 이것을 수정하기 위해 코드를 수정하려면 어떻게해야합니까?

// Fourth_Layer (C#2005 콘솔 응용 프로그램)

class FourthLayer
{
    static void Main(string[] args)
    {
        ThirdLayer thirdLayer = new ThirdLayer();
        thirdLayer.PassDataBackToCaller();
    }
}

// Third_Layer (VC ++ 2005 클래스 라이브러리)

public ref class ThirdLayer
{
    private:
        SecondLayer *_secondLayer;

    public:
        ThirdLayer();
        ~ThirdLayer();
        void PassDataBackToCaller();
};

ThirdLayer::ThirdLayer()
{
    _secondLayer = new SecondLayer();
}

ThirdLayer::~ThirdLayer()
{
    delete _secondLayer;
}

void ThirdLayer::PassDataBackToCaller()
{ 
    StdVectorWrapper v;
    _secondLayer->PassDataBackToCaller(v);

    for (int i=0; i<v.GetSize(); i++)
    {
        StdStringWrapper s = v.GetNext();
        std::cout << s.CStr() << std::endl;
    }
}

// Second_Layer- 메인 클래스 (VC ++ 6 Win32 DLL)

class SECOND_LAYER_API SecondLayer
{
    private:
        FirstLayer *_firstLayer;

    public:
        SecondLayer();
        ~SecondLayer();
        void PassDataBackToCaller(StdVectorWrapper &toCaller);

    private:
        void ConvertToStdVectorWrapper(
            const std::vector<std::string> &in, StdVectorWrapper &out);
};

SecondLayer::SecondLayer() : _firstLayer(new FirstLayer())
{
}

SecondLayer::~SecondLayer()
{
    delete _firstLayer;
}

void SecondLayer::PassDataBackToCaller(StdVectorWrapper &toCaller)
{ 
    std::vector<std::string> v;
    _firstLayer->PassDataBackToCaller(v);
    ConvertToStdVectorWrapper(v, toCaller);
}

void SecondLayer::ConvertToStdVectorWrapper(
    const std::vector<std::string> &in, StdVectorWrapper &out)
{
    for (std::vector<std::string>::const_iterator it=in.begin(); it!=in.end(); ++it)
    {
        StdStringWrapper s((*it).c_str());
        out.Add(s);
    }
}

// Second_Layer -StdVectorWrapper Class (VC ++ 6 Win32 DLL)

class SECOND_LAYER_API StdVectorWrapper
{
    private:
        std::vector<StdStringWrapper> _items;
        int index;  

    public: 
        StdVectorWrapper();
        void Add(const StdStringWrapper& item);
        int GetSize() const;  
        StdStringWrapper& GetNext(); 
};

StdVectorWrapper::StdVectorWrapper()
{
    index = 0;
}

void StdVectorWrapper::Add(const StdStringWrapper &item)
{
    _items.insert(_items.end(),item);
}

int StdVectorWrapper::GetSize() const
{
    return _items.size();
}

StdStringWrapper& StdVectorWrapper::GetNext()
{
    return _items[index++];
}

// Second_Layer -STDSTRINGWRAPPER CLASS (VC ++ 6 Win32 DLL)

class SECOND_LAYER_API StdStringWrapper
{
    private:
        std::string _s;

    public:  
        StdStringWrapper();
        StdStringWrapper(const char *s);
        void Append(const char *s);
        const char* CStr() const;  
};

StdStringWrapper::StdStringWrapper()
{
}

StdStringWrapper::StdStringWrapper(const char *s)
{
    _s.append(s);
}

void StdStringWrapper::Append(const char *s)
{
    _s.append(s);
}

const char* StdStringWrapper::CStr() const
{
    return _s.c_str();
}

// First_Layer (VC ++ 6 Win32 DLL)

class FIRST_LAYER_API FirstLayer
{
    public:
        void PassDataBackToCaller(std::vector<std::string> &toCaller);
};

void FirstLayer::PassDataBackToCaller(std::vector<std::string> &toCaller)
{
    std::string a, b;
    a.append("Test string 1"); 
    b.append("Test string 2");
    toCaller.insert(toCaller.begin(),a);
    toCaller.insert(toCaller.begin(),b);
}
도움이 되었습니까?

해결책

솔루션을 찾았습니다. 기본적으로 두 가지 문제가 있습니다.

문제 1 (FirstLayer와 Secondlayer 사이)

기본적으로 VC ++ 6의 다음 설정은 멀티 스레드입니다. 이 설정은 FirstLayer와 SecondLayer 모두에 대해 멀티 스레드 DLL로 변경해야합니다. 두 가지 모두 작동하기 위해이 새로운 설정과 재 컴파일해야합니다.

프로젝트-> 설정-> C/C ++ Tab-> 카테고리 : 코드 생성-> 런타임 라이브러리 사용-> 멀티 스레드 DLL

문제 2 (Secondlayer와 Thirdlayer 사이)

내가 쓴 stdstringwrapper 및 stdvectorwrapper 클래스는 딥 카피를 구현하지 않습니다. 따라서 딥 카피를 구현하기 위해 STDSTRINGWRAPPER 및 STDVECTORWPRAPPER 클래스에 다음을 추가하는 것입니다.

  • 생성자 복사
  • 과제 연산자
  • 해체 조치

편집하다: 문제 2에 대한 대체 솔루션

더 나은 솔루션은 사용하는 것입니다 clone_ptr std :: 벡터에 포함 된 모든 요소와 std :: 벡터 자체에 대해. 이는 카피 생성기, 할당 연산자 및 해체가 필요하지 않습니다. 그래서 stdvectorwrapper 클래스 내에서 당신은 그것을 다음과 같이 선언합니다.

clone_ptr< std::vector< clone_ptr< StdStringWrapper > > > _items;

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