Проблема с указателем в C ++ / CLI = весело! - PullRequest
1 голос
/ 08 октября 2010

Я конвертировал кучу старого кода C ++ в код C ++ / CLI и думаю, что закодировал себя в угол.

Моя цель состояла в том, чтобы взять неуправляемую библиотеку c ++ и кучузаголовочных файлов и раскрыть их функциональность для решения C #.Из чтения в интернете стандартный способ сделать это:

  • Создать два класса c ++: один управляемый, другой неуправляемый.
  • Неуправляемый класс будет сворачивать объекты вбиблиотека c ++ для обеспечения желаемой функциональности.
  • Управляемый класс обернет все открытые методы в неуправляемом классе.Каждый метод-обертка будет обрабатывать необходимые преобразования из String ^ в строку и т. Д.

Но мой сценарий не очень сложен, поэтому я решил просто попытаться реализовать все в одном классе.Сейчас я борюсь со специфической проблемой, которая генерирует AccessViolationExceptions.

Мой заголовочный файл выглядит так:

public ref class ManagedClass
{
public:
  ManagedClass();
  void CreateUnmanagedObject(String^ param1);
  void UseUnmanagedObject();

  UnmanagedObject *myUnmanagedObject;
}

И мой файл cpp выглядит так:

void ManagedClass::CreateUnmanagedObject(String^ param1)
{
   /* Convert params, use them in some way. */

   /* capture the output of this library call to the pointer defined in ManagedClass.*/
   myUnmanagedObject= &(LibrayObject.LibraryMethod1());  
}
void ManagedClass::UseUnManagedObject()
{
   /* This function will pass the Unmanaged object into
    * a library function which will do some work on it.
    */
   LibraryObject.LibraryMethod2(*myUnmanagedObject);
   /* Whoops! System.AccessViolationException is thrown! */
}

Интересно, что если я вызываю LibraryMethod2 внутри CreateUnmanagedObject сразу после LibraryMethod1, он работает нормально.Но после выхода CreateUnmanagedObject кажется, что память, на которую указывает myUnmanagedObject, потеряна.

Может кто-нибудь увидеть причину, по которой это происходит?

Редактировать: объявления библиотеки выглядят так:

UnmanagedObject LibraryMethod1();
void LibraryMethod2(UnmanagedObject &param);

Ответы [ 3 ]

1 голос
/ 08 октября 2010

Не уверен, в чем может быть ваша настоящая проблема, но все выглядит неправильно. Управляемая оболочка должна быть довольно близка к неуправляемой. Давайте работать из неуправляемой декларации, например:

class Unmanagedclass {
public:
    Unmanagedclass(const char* arg) {}
    void mumble() {}
};

Тогда ваша обертка должна выглядеть примерно так:

#pragma managed(push, off)
#include "unmanagedclass.h"
#pragma managed(pop)

using namespace System;
using namespace System::Runtime::InteropServices;

public ref class ManagedWrapper
{
    Unmanagedclass* instance;
public:
    ManagedWrapper(String^ arg) {
        IntPtr mem = Marshal::StringToCoTaskMemAnsi(arg);
        instance = new Unmanagedclass((char*)(void*)mem);
        Marshal::FreeCoTaskMem(mem);
    }
    ~ManagedWrapper() {
        delete instance;
        instance = 0;
    }
    !ManagedWrapper() {
        delete instance;
    }
    void mumble() {
        instance->mumble();
    }
};

Рецепт здесь заключается в том, что экземпляр неуправляемого класса является указателем в оболочке. И просто делегируйте вызовы управляемого метода неуправляемому. Да, какой-нибудь хоккей-ключ со строками, как показано на рисунке. И убедитесь, что этот собственный экземпляр удаляется, когда к нему или пользователь, или сборщик мусора.

1 голос
/ 08 октября 2010

Вы не берете адрес временной переменной? Если

LibraryObject.LibraryMethod1()

возвращает копию некоторого значения, затем вы берете адрес локальной переменной, которая выходит из области действия в конце метода. Использование этого адреса впоследствии является неопределенным поведением, в данном случае это вызывает нарушение прав доступа!

0 голосов
/ 08 октября 2010

Вы берете указатель на переменную on-stack-temp.По счастливой случайности, это указывает на что-то, если вы вызываете методы один за другим.

Я пишу что-то на c ++ после многих лет комфорта c # и должен сказать, что время от времени у меня возникают одни и те же проблемы.1003 *

Короче говоря - не берите адрес чего-то, что было создано временно, и сохраняйте его в указателе для последующего использования.Период.

...