Плюсую за этот вариант, несколько раз пользовался. Преимущества перед классическим pinvoke:
все описания в одном месте, нет необходимости "не забыть поправить C#" если изменил контракт на сишной стороне
гораздо прозрачнее менеджмент памяти: CLI поддерживает как managed-пулы памяти, так и native, делаем на стыке двух миров все необходимые преобразования и отпускаем память если больше не надо
енумы — опять же, см. пункт 1, описываем в одном месте (С++) и CLI выставит его на дотнетную часть, главное в отдельный namespace не забыть обернуть — иначе не увидит, global namespace оно не экспортирует
все проверки — compile time