Преобразование из указателя С++/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()