Могут ли C # и C ++ взаимодействовать для высокопроизводительного кода? - PullRequest
1 голос
/ 13 мая 2011

У нас есть устаревший код C ++, выполняющий высокопроизводительную обработку данных (например, большие объемы данных, поступающие с аппаратных устройств, которые обрабатываются с учетом времени для отображения, преобразования и передачи во вторичное хранилище).

Нас интересует C # / .NET для новых графических интерфейсов и новых утилит (существующие графические интерфейсы - C ++ MFC и Qt). Конечно, в существующей системе у нас нет проблемы «языкового перевода» для виртуальной машины .NET (весь существующий код - C ++).

После долгих исследований и множества книг я не уверен, что это можно сделать эффективно. Возможные подходы (я что-то пропустил?):

  1. Переписать все в .NET (не могу случается - слишком много кода, доступ к «голому железу», обработка тяжелого алгоритма, чувствительного ко времени)
  2. Тонкий слой адаптера для Managed C ++ / CLI
  3. Толстый переходный слой для Managed C ++ / CLI
  4. Не используйте .NET (менеджеры чувствуют себя прекрасно печаль)

Мы обеспокоены (2) «тонким слоем адаптера» в том, что было бы неплохо, если бы графические интерфейсы могли (повторно) использовать логику на «деловом» уровне (многие свойства были получены алгоритмически), поэтому, если мы не будем Если открыть / обернуть классы C ++, большая часть логики графического интерфейса будет просто копировать существующую логику C ++ на бизнес-уровне.

Мы обеспокоены тем, что (3) «толстый слой адаптера» заключается в том, что оборачивать каждый класс C ++ классом C # очень утомительно (дорого), и в нескольких книгах предлагается доступ к боксам / распаковкам через эту границу, что может свидетельствовать о таком подходе. довольно нереализуемо / непомерно (это слишком сильно по производительности, чем тривиальные конструкции).

Как бы вы взаимодействовали с новым C # / .NET (GUI) поверх структуры глубокого обогащения классов, реализованной в C ++?

Ответы [ 2 ]

5 голосов
/ 14 мая 2011

C ++ / CLI идеально подходит для этого. С управляемой / неуправляемой трансляцией нет проблем с производительностью, поскольку C ++ / CLI использует ту же оптимизированную технику вызовов, которая используется самим механизмом исполнения .NET для реализации высокопроизводительных методов, таких как конкатенация строк.

Проблемы с производительностью возникают, когда вы копируете данные туда и обратно между .NET и собственными версиями одной и той же структуры данных, но у вас будет такая же проблема, например, использование библиотеки, которая использует BSTR наряду с библиотекой, которая использует std::string, и медленные операции одинаково очевидны (в отличие от P / Invoke, который пытается сделать эти переводы прозрачными и в конечном итоге скрывает проблемы производительности в процессе).

Есть также некоторые приемы, которые вы можете использовать, чтобы преодолеть это. Например, вместо копирования std::vector в System::Collections::Generic::List, реализуйте IEnumerator, который непосредственно читает из std::vector.

И, конечно, если данные просто будут передаваться непосредственно в другую функцию C ++, нет никакой причины преобразовывать их в управляемый тип вообще. Опять же, C ++ / CLI упрощает сохранение формата, когда P / Invoke пытается конвертировать все, что у вас за спиной.

Таким образом, «тонкий» слой оболочки C ++ / CLI - лучший из ваших вариантов.

2 голосов
/ 13 мая 2011

У вас есть правильное представление об ограничениях.Пересечение границы стоит дорого, вы не хотите делать это для мелкозернистых операций.Как мелкозернистый? Конечно, это зависит .

В идеальном случае ваш код C ++ наслоен на рациональную объектную модель, поверх которой вы можете поместить слой COM (или аналогичный) для более масштабных операций.,В качестве одного примера, вместо того, чтобы выставлять объект с 5 свойствами и парой сеттер / получатель для каждого из них, вы хотите выставить метод SetProperties (), который принимает карту всех свойств, которые должны быть установлены.Это ни в коем случае не единственный случай, на который нужно обратить внимание;это всего лишь пример того, как склонить себя к более масштабным операциям.

Про COM - это приятно, но, конечно, не обязательно.Использование COM навязывает вам дисциплину, так как вам необходимо формально определить операции в интерфейсе COM.Без формального принуждения, обеспечиваемого COM, ваша команда могла бы «обмануть» - и раскрыть многочисленные тактические точки интеграции между уровнями, что может привести к подлым проблемам с производительностью.

Если у вас есть надежное управление проектом и хорошая командачлены, тогда вы могли бы обеспечить соблюдение этих стандартов проекта, не полагаясь на формальность COM.Определите ваши собственные классы-оболочки в C #, через которые происходит все пересечение границ.

Суть в том, я подозреваю, что вы не будете знать точно правильное решение, пока не поиграете с ним и не протестируете его.

Соберите пару членов команды, хороших разработчиков, и попросите их создать прототипы двух разных вариантов.Например, тонкий против толстого, где точные значения этих терминов определены вами.Дайте им 3 недели или около того, чтобы что-то собратьЗатем измерьте их производительность и производительность и примите решение на основе этого.

...