Сохранить указатель C ++ в C# - PullRequest
0 голосов
/ 18 апреля 2020

На данный момент я пишу небольшую Программу на C#, которая включает в себя C ++ Dll.

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

C++:
__declspec(dllexport) FrameCapture* GetFrameCapturer(HWND windowHandle) {
    ProcessWindow* window = ProcessWindowCollection::GetInstance()->FindWindow(windowHandle);
    FrameCapture* capture = new FrameCapture(window);
    return capture;
}

Как вы можете видеть, я просто создаю класс FrameCapture и возвращаю ему указатель.

Этот указатель хранится в C# как IntPtr .

C#:
[DllImport("<dllnamehere>")]
public static extern IntPtr GetFrameCapturer(IntPtr windowHandle);

Пока это работает очень хорошо. Но если я использую этот указатель для получения экземпляра FrameCapture

C++:
__declspec(dllexport) BITMAPFILEHEADER* GetBitmapFileHeader(FrameCapture* frameCapturer) {
    return frameCapturer->GetBitmapFileHeader();
}

, класс будет полностью пустым. Как получить экземпляр класса I, инициализированный на первом этапе?

РЕДАКТИРОВАТЬ:

Я провел некоторое тестирование и заменил указатели на целые числа, на которые лучше смотреть.

Я произвел «захват» в Int32 и вместо этого вернул его. В моем тестовом примере он вернул байт (208,113,244,194). Эти значения, как и ожидалось, в C ++ и C# одинаковы.

Но теперь они становятся нечетными.

Если я передаю этот Int32 в 'GetBitmapFileHeader', значение становится внезапно байтовым ( 184,231,223,55).

Это даже не близко! Я думал о Little <-> Big Endian или что-то вроде этого, но это совершенно новый блок памяти?

То же поведение будет go с IntPtr.

По запросу я отправляю также импорт GetBitmapFileHeader

[DllImport("<dllnamehere>")]
public static extern tagBITMAPFILEHEADER GetBitmapFileHeader(IntPtr capturerHandle);

1 Ответ

0 голосов
/ 19 апреля 2020

Хорошо, я понял.

См. Этот импорт из C#.

C#:
[DllImport("<dllnamehere>")]
public static extern tagBITMAPFILEHEADER GetBitmapFileHeader(IntPtr capturerHandle);

Это неправильно!

Функция теперь возвращает IntPtr, который работает полностью хорошо.

Это новая настройка:

C ++:

    __declspec(dllexport) void* __stdcall GetBitmapFileHeader(void* frameCapturer) {

        FrameCapture* cap = (FrameCapture*)frameCapturer;
        return cap->GetBitmapFileHeader();
    }

C#:

[DllImport("libWinCap.dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetBitmapFileHeader(IntPtr frameCapturer);

[...]
//calling
IntPtr ptr = GetBitmapFileHeader(m_capturerHandle);
m_bitmap.m_fileHeader = (tagBITMAPFILEHEADER)Marshal.PtrToStructure(ptr, typeof(tagBITMAPFILEHEADER));

Теперь я перемещаю только указатели и используйте PtrToStructure для чтения памяти.

Также, спасибо за каждый комментарий.

...