Как передать struct как параметр из c ++ / cli в c ++

0

Мой код состоит из трех частей: С#, c++/cli, c++.

в С# у меня есть структура. Структура определяет параметры передачи.

//c#
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack=1)]
public struct NDeviceDest
{
    public uint IP;

    public uint pos;
}

Затем в c++/cli у меня есть функция, которая использует NDeviceDest

//c++/CLI
byte NDockMaster::Init(NDeviceDest pos, uint param)
{
    m_pDockMaster->Init(static_cast<DeviceDest*>pos, param);
}

* m_pDockMaster * - это указатель на собственный тип.

Функция-член Init определяется в c++ как()

//c++
struct DeviceDest
{
UINT32          IP;     
unsigned int    pos;                                
};

class DockMaster
{
public:
    byte Init(DeviceDest* dest, UINT32 param)
    {
        return 0;
    }
}

DeviceDest определяется как то же, что и NDeviceDest, для передачи параметров.

Вопрос:

В моем коде c++/cli я использую * static_cast *, чтобы изменить тип. но я получил ошибку компиляции:

error C2440: 'static_cast' : cannot convert from 'NDeviceDest' to 'DeviceDest *'

Я новичок в c++/cli, но я думаю, что ДОЛЖЕН быть способ сообщить компилятору, что NDeviceDest - это DeviceDest, и позвольте мне скомпилировать и передать значение из С# в cli, затем в c++, но я искал и не нашел точного ответа.

Я нашел некоторый код, но с помощью указателей, а не структур, я также пытался использовать указатели, но у меня такая же ошибка.

благодаря

Теги:
struct
c++-cli

3 ответа

4
Лучший ответ

Нет, компилятор не позволит вам это сделать. Даже C-стиль cast или reinterpret_cast <>() будет работать, самое большое оружие, которое у вас есть.

Это очень хорошая причина, управляемые структуры совершенно несовместимы с неуправляемыми структурами. Первая проблема - это макет, точный порядок и смещение членов структуры. Что технически является меньшей проблемой, CLR уже делает попытку сохранить их одинаковыми. Обычно это матч, не всегда. Вы найдете более подробную информацию в этом сообщении.

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

Поэтому он просто запрещает это. Структура должна быть маршалирована, скопирована в неуправляемую память и перестроена в соответствии с исходным макетом. Универсальная вспомогательная функция - Маршал :: StructureToPtr(). Но совершенно ненужный для такой небольшой структуры, гораздо быстрее и проще копировать поля самостоятельно:

  Byte Init(NDeviceDest pos, unsigned param) {
      DeviceDest unmanagedPos = { pos.IP, pos.pos };
      m_pDockMaster->Init(&unmanagedPos, param);
      //...
  }

Что соответствует требованиям, оно гарантировало правильную компоновку. И выделяется в стабильной памяти, GC не вмешивается в расположение стека, а память стабильна в течение всего времени выполнения метода. В случае, если это нужно сказать, вероятно, нет, убедитесь, что "DockMaster" не сохраняет пройденный указатель.

  • 0
    я думаю, что дополнительные локальные неуправляемые посты очень утомительны. Мне было интересно, так как я звоню из c ++ / cli, может быть, c ++ / cli более умный, чем обычный .net / clr, и знает, что на самом деле происходит?
  • 0
    Взаимодействие утомительно, к нему нужно привыкнуть. Он знает, что происходит, это не законно и говорит вам об этом. Вам решать, чтобы выбрать альтернативу, как указано, есть больше, чем один.
Показать ещё 2 комментария
0

Если это проблема поиска класса, и если вы используете указатели, и вы уверены, что ваш маршалинг правилен, попробуйте использовать reinterpret_cast.

m_pDockMaster->Init(reinterpret_cast<DeviceDest*>pos, param);

Но на первый взгляд вы пытаетесь преобразовать не указательный тип в тип указателя. Вы должны использовать NDeviceDest * pos в качестве входного параметра или

m_pDockMaster->Init(static_cast<DevideDest*>&pos,param) .
0

Ошибка, которую вы видите, заключается в том, что static_cast не разрешается преобразовывать (преобразовывать) из struct в struct *. Поэтому правильный вызов в интерфейсе c++/cli был бы

m_pDockMaster->Init(static_cast<DeviceDest*>(&pos), param);

  • 0
    Да, сообщение об ошибке (не удается преобразовать из 'NDeviceDest' в 'DeviceDest *') меня смутило. Если он говорит «от структуры к структуре *» (как вы сказали), это будет очень полезно для меня. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню