Как передать InteropServices.ComTypes.IStream нативному методу, принимающему IStream *, используя c ++ / cli - PullRequest
0 голосов
/ 03 января 2019

У меня есть нативный dll с управляемой оболочкой, все написано и работает с COM-взаимодействием. Моя работа сейчас состоит в том, чтобы переписать оболочку (и части библиотеки DLL) с помощью c ++ / cli.

Один из методов в нативной dll принимает указатель IStream * output в качестве одного из аргументов, и именно здесь я застрял. Всякий раз, когда я пытаюсь использовать указатель выход , я получаю AccessViolationException .

Вот иллюстрация того, как выглядит мой код:

common.h

class INativeClass
{
public:
    virtual int NativeMethod(IStream* output) = 0;
};

c ++ native

#include "common.h"

public NativeClass : public INativeClass  
{  
    public int NativeMethod(IStream* output)  
    {  
        outputStream->Write(...); //AccessViolationException happens here
    }  
}

c ++ удалось

#include "common.h"

public ref class ManagedClass  
{  
private:  
    INativeClass* nativeObject;  

public: 

    ManagedClass()  
    {  
        nativeObject = CreateNewNativeObject();  
    }  

    int ManagedMethod(IStream^ output)  
    {  
        NativeClass nativeObject = new 
        GCHandle streamHandle = GCHandle::Alloc(output);  
        IntPtr ipo = GCHandle::ToIntPtr(streamHandle);  
        nativeObject->NativeMethod(static_cast<IStream*>(ipo.ToPointer()));  
    }  
}  

с #

void main()  
{  
    ManagedClass managedObject = new ManagedClass();  
    IStreamImplementation stream = new IStreamImplementation(filepath);  
    managedObject.ManagedMethod(stream);  
}

Я искал в интернете несколько дней и не могу понять, что я делаю неправильно. Я думаю, что я преобразовал в IStream * правильно, и что мне не нужно беспокоиться о GC. Я также пытался использовать pin_ptr , но это не помогло.

Если это дубликат, я прошу прощения, но, как я уже сказал, я уже несколько дней ищу решение.

EDIT

Обновлен код с минимальным компилируемым кодом, который повторяет проблему (может отсутствовать несколько включений).
Также, когда я говорю IStream, я имею в виду InteropServices.ComTypes.IStream или его аналог на С ++. Я не использую std :: istream

1 Ответ

0 голосов
/ 20 мая 2019

Я решил эту проблему, выполнив то, что сказал Ганс Пассант:

В ManagedClass у меня есть:

int ManagedMethod (IStream^ output)
{
    IntPtr outputPtr = Marshal::GetIUnknownForObject(output);
    IUnknown* outputNativePtr = static_cast<IUnknown*>(outputPtr.ToPointer());
    nativeObject->NativeMethod(outputNativePtr);
}

В NativeClass у меня есть:

int NativeMethod(IUnknown* output)
{
    IStream outputStream;
    HRESULT hr = output->QueryInterface(IID_IStream, (void**)&outputStream);
    if (FAILED(hr) || outputStream == nullptr)
    {
        //error
    }
    //do something
}
...