Pergunta

First_Layer

Eu tenho um dll win32 escrito em VC ++ 6 Service Pack 6. Vamos chamada esta dll como FirstLayer. Eu não tenho acesso ao código fonte do FirstLayer mas eu preciso chamá-lo de gerenciado código. O problema é que FirstLayer faz uso pesado de std :: vector e std :: string e não há nenhuma maneira de empacotamento desses tipos em um aplicativo C # diretamente. O código para esta camada abaixo ilustra um exemplo do que pode ser encontrado neste dll.

Second_Layer

A solução que eu posso pensar é a primeira a criar outra dll win32 escrito em VC ++ 6 Service Pack 6. Vamos chamada esta dll como "SecondLayer". SecondLayer atua como um wrapper para FirstLayer que basicamente converte tipos de STL em tipos não de classe STL personalizados escrito.

Third_Layer

Eu também criou um VC ++ biblioteca de classe 2005 como um wrapper para SecondLayer. Este invólucro faz todo o trabalho sujo de converter o SecondLayer não gerenciado em código gerenciado. Vamos chamar essa camada como "ThirdLayer". O código para esta camada como mostrado abaixo é simplificada para demonstrar o erro de modo que não fazer a conversão acima mencionada.

Fourth_Layer

Para cima de tudo, eu criei um C # 2005 aplicativo de console para chamar ThirdLayer. Vamos chamar esse aplicativo de console C # como "FourthLayer".

Resumo de chamadas Sequence

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

O erro de execução

O código abaixo compilação / compilação sem erros, mas eu recebo o seguinte erro de tempo de execução:

Exceção não tratada: System.AccessViolationException: Tentativa de ler ou memória protegida gravação. Isso é muitas vezes uma indicação de que outra memória está corrompida. em SecondLayer.PassDataBackToCaller (SecondLayer , StdVectorWrapper *) em Sample.ThirdLayer.PassDataBackToCaller () em c: \ project \ em ir teste projetos \ \ sample \ thirdlayer \ thirdlayer.cpp: linha 22 em FourthLayer.Program.Main (String [] args) em C: \ Project \ Going On Projects \ test \ Sample \ FourthLayer \ Program: linha 14 *

Este erro não é necessário que aparecem quando a aplicação FourthLayer é executado no sistema operacional diferente. Por exemplo, para o Windows XP, há nenhum erro, mas por outro sistema operacional como o Vista e Windows 7, o erro vai aparecer.

Eu não entendo o que está causando isso. Alguma ideia? Como posso ir sobre como modificar o código para corrigir isso?

// Fourth_Layer (C # 2005 aplicativo console)

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

// Third_Layer (VC ++ 2005 biblioteca de classes)

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 - classe principal (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);
}
Foi útil?

Solução

Eu encontrei a solução. Bascially, existem dois problemas com ele.

Problema One (Entre FirstLayer e SecondLayer)

Por padrão, a seguinte configuração de VC ++ 6 é multithread. Esta definição tem de ser alterado para Multithreaded DLL para tanto o FirstLayer e SecondLayer. Ambos os quais deve ser com esta nova configuração para que ele funcione compilado-re.

Projeto-> Configurações> C / C ++ tabulação> Categoria: Código Generation-> Use run-time biblioteca-> Multithreaded DLL

Problema Two (Entre SecondLayer e ThirdLayer)

A classe StdStringWrapper e StdVectorWrapper que eu escrevi não implementar cópia profunda. Então tudo necessidade I a fazer é adicionar a seguinte para a classe StdStringWrapper e StdVectorWrapper para implementar cópia profunda.

  • Construtor de cópia
  • Operador de atribuição
  • Deconstructor

Editar: Solução Alternativa para o problema Two

Um ainda melhor solução seria usar clone_ptr para todos os elementos contidos no std :: vector, bem como para std :: próprio vector. Isso elimina a necessidade do construtor de cópia, operador de atribuição e deconstructor. Então, dentro da classe StdVectorWrapper, você declará-lo como

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top