Преобразование из указателя С++/CLI в собственный указатель С++

Я столкнулся с этой проблемой преобразования указателя С++/CLI в собственный указатель на С++. Это фон: Я пишу приложение форм Windows, используя С++/CLI. Приложение выполняет вызов на несколько COM-интерфейсов. При создании экземпляра (внутри класса С++/CLR) объекта через интерфейс COM, я передаю (void**)(&provider) в качестве последнего аргумента в CoCreateInstance, как в:

HRESULT CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider));

Однако я получаю ошибку компилятора: невозможно преобразовать из cli::interior_ptr<Type> в void **. Я сделал som исследований в этом, и похоже, что это проблема различных типов указателей в С++ и С++/CLI. Кто-нибудь знает об этом и, возможно, подскажет, как это можно исправить? Thanx заранее!

Во-первых, спасибо за вашу помощь!

Как предложил Фрейх, я попытался использовать pin_ptr, но вместо этого компилятор жаловался на проблемы с преобразованием из interior_ptr в pin_ptr. Если я вместо этого попытаюсь использовать interior_ptr, как в:

pin_ptr<void *> pinnedPtr = &provider;
CoCreateInstance(CLSID_MSPRProvider, NULL, CLSCTX_LOCAL_SERVER, IID_IMSPRProvider, ( void** )pinnedPtr);

Я получаю не могу конвертировать из interior_ptr в interior_ptr. Все сводится к проблеме преобразования interior_ptr в void**. Например: (void**)interiorPtr, где interiorPtr, конечно, есть interior_ptr. Любые идеи в этом?

Ответы

Ответ 1

Я считаю, что вы должны пометить указатель как "закрепленный" (в управляемом коде), а затем скопировать байты в некоторую неуправляемую область памяти, а затем использовать указатель на это. Например, здесь фрагмент кода, который я однажды получил где-то, который преобразует указатель на управляемую System:: String в неуправляемый UTF-8 неуправляемый std::string:

std::string managedStringToStlString( System::String ^s )
{
    Encoding ^u8 = Encoding::UTF8;
    array<unsigned char> ^bytes = u8->GetBytes( s );
    pin_ptr<unsigned char> pinnedPtr = &bytes[0];
    return string( (char*)pinnedPtr );
}

Обратите внимание, как мне нужно получить "закрепленный" указатель на массив bytes, возвращаемый функцией GetBytes(), а затем передать его в char*, прежде чем передать его в конструктор std::string. Я считаю, что это необходимо, чтобы избежать того, что подсистема управляемой памяти перемещает массив bytes в памяти, когда я копирую байты в строку STL.

В вашем случае попробуйте заменить

CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)(&provider)); 

с

pin_ptr<void *> pinnedPtr = &provider;
CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, (void**)pinnedPtr); 

и посмотрите, работает ли это.

Ответ 2

В течение некоторого времени я использовал С++/CLI, но я думаю, что вам нужно прикрепить указатель.

Ответ 3

Ожидается ли, что память указала, что она действительна за пределами вызова CoCreateInstance()?

Как упоминал Фрерих и Ахим, вы можете получить необработанный указатель на память, не опасаясь переустановки памяти, путем "закрепления" и получения указателя на внутреннюю область. Обычно вы делаете это с помощью шаблона pin_ptr (см. Статью Frerich для примера).

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

Поэтому, если для вызова CoCreateInstance() требуется только память, то pin_ptr - это путь. Если нет, вам придется взять копию памяти и передать ее на CoCreateInstance()