Ссылка отслеживания на проблему с родной ссылкой - C # для C ++ / CLI для C ++ AccessViolationException - PullRequest
0 голосов
/ 06 августа 2011

Я пытаюсь написать оболочку C ++ / CLI, используя VS2010, против API C ++, для которого у меня есть доступ только к заголовочным файлам и файлу dll / lib.

У меня возникла проблема с копированием резервной копии нативной ссылки из нативного кода в ссылку на отслеживание в коде C #. Я получаю SystemAccessViolation. Код выглядит следующим образом:

Неуправляемые собственные заголовки C ++ для собственных функций, которые возвращают ссылку на создание, а также на изменение пользовательского объекта:

class ManageCustomObject;
    _declspec(dllimport) errorCode CreateCustomObject(CustomObject& customObject);
    _declspec(dllimport) errorCode ModifyCustomObject(CustomObject& customObject);

Важно отметить, что CustomObject имеет только частные конструкторы:

CustomObject(const CustomObject&) { }
CustomObject& operator=(const CustomObject&) { return *this; }

Теперь мой метод уровня C ++ / CLI выглядит следующим образом:

public ref class WrapperManageCustomObject {
public:
        errorCode WrapperCreateCustomObject(CustomObject% customObject)
        {
            return CreateCustomObject(customObject);
       }

        errorCode WrapperModifyCustomObject(CustomObject% customObject)
        {
            return ModifyCustomObject(customObject);
        }
};

И оболочка для CustomObject выглядит следующим образом:

public class WrapperCustomObject : public CustomObject {
    public:
        WrapperCustomObject(const CustomObject&) {};
};

В C # код выглядит следующим образом:

WrapperCustomObject wrapperCustomObject;
WrapperManageCustomObject wrapperManageCustomObject = new WrapperManageCustomObject();

long result;

// this works great
result = wrapperManageCustomObject.CreateCustomObject(ref wrapperCustomObject);

// can utilize wrapperCustomObject here with other native functions no problem, so long as I don't try to modify it...
...

// this throws an AccessViolationException was unhandled message
// essentially I am modifying / returning a different native customObject (though I'm not 100% sure what it does as I do not have access to the code)
result = wrapperManageCustomObject.ModifyCustomObject(ref wrapperCustomObject);

Как вы можете видеть в моих комментариях, попытка изменить этот объект с помощью ссылки выдает «AccessViolationException не обработан: попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена».

Теперь, если я исключу из этого уравнения C # и ссылку на отслеживание и сделаю все это в C ++ или C ++ / CLI (если ссылка на отслеживание отсутствует), это работает нормально. Я предполагаю, что это как-то связано с собственным кодом, пытающимся получить доступ к обновлению ссылки, которая теперь находится в управляемой земле.

Есть ли способ обойти это, чтобы по существу заставить этот код "работать" изнутри C #? Нет способа передать нативную ссылку на C #, о которой я знаю.

1 Ответ

0 голосов
/ 06 августа 2011

Управляемые ссылки абсолютно не похожи на нативные ссылки. Управляемые ссылки больше похожи на нативные указатели. Насколько я знаю, вы не можете делать что-то вроде public class WrapperCustomObject : public CustomObject (где CustomObject - нативный класс) и никогда не ожидать, что это сработает. Когда вы создаете управляемый класс, вы говорите CLR, что ваш класс будет хорошо себя вести перед лицом перемещения в памяти. Если CustomObject вообще что-то делает с указателями, это больше не будет правдой. CustomObject не использует управляемые ссылки, и поэтому среда выполнения не может знать, где обновлять клиентов, если / когда этот экземпляр класса перемещается.

Хуже того, ваша оболочка позволяет создавать экземпляры этого класса без прохождения фабричного метода. Поэтому, если фабричный метод CreateCustomObject делает что-то важное для возвращаемого объекта, вы нарушили контракт вызываемого кода, который попросил вас создать экземпляры этого объекта только через фабричный метод.

...