Pull to refresh

Comments 13

А почему бы не использовать промежуточную библиотеку на Managed C++? Которая брала бы данные в «родном» для С# виде и преобразовывала бы в требуемый для C++ библиотеки.

В результате получили бы красивый интерфейс на C#, без вот этих всех дублированных counters + countersCount и "[StructLayout(LayoutKind.Sequential, Pack = 4)]"
Про этот вариант я подумал только тогда, когда уже сделал маршалинг из C#.

counters и сountersCount — были заданы в изначальной библиотеке, поэтому от них избавиться вряд ли получилось бы.

Но насколько я понимаю, что это был-бы тот же маршалинг, только прописанный руками, а как следствие. В случае, если придется менять формат данных, то правке будут подлежать три dll: сама библиотека, библиотека на VC++ и библиотека на C#. При таком же маршалинге стандартными средствами, править придеться только 2 dll.
Нет, я про то, чтобы для C# интерфейс был таким —
public class ConfCounter
{
public int adress;
public int number;
public MSR[] config;
}

В вашем варианте программисту вручную каждый раз придётся заполнять поле configCount. Что когда-нибудь аукнется.

Кроме того, я не совсем понял, как при маршалинге activityName превращается из wchar_t в std::wstring. Объясните, пожалуйста.
У std::wstring есть перегрузка операции присваивания для wchar_t*, то есть там в C++ методе идет перевод в изначальные структуры — присваиванием.
Что-то типа:
VPS::ErrorCode InitConfig2(ManagedTemp::vpsConfig* conf)
{
vpsConfig conf1;
conf1.ActivityName = conf->ActivityName;
//аналогичные действия

return InitConfig(conf1);
}


Про заполненность полей.
Эта структура нигде не инициализируется программистом явно. Структура с конфигурацией собирается из xml-конфига. А этот конфиг в свою очередь генерируется с помощью GUI. То есть шанс получить не валидную конфигурацию — только один. Менять значения в сгенерированной xml вручную. При этом будет просто сгенерировано исключение.
Так вы всё равно же делаете переприсвоение всех полей из managed структуры в поля структуры на C++. Зачем тогда все эти дополнительные атрибуты и лишние поля?
Атрибуты нужны для вызова функции из native dll. Лишних полей тут нет, так как в С++ коде идет переход к динамическому массиву.

Сравнивая это вариант с VC++ — видна выгода, о которой я написал выше, что изменения, если они будут, затронут всего две dll, а не три.

Спасибо, что обратили внимание на то что выигрыш не настолько существенен.
Это вы ещё не вытаскивали вручную адреса методов из vtable, из-за того, что в системной либе криво реализован IUnknown (QueryInterface возвращает E_NOTIMPL) и у маршалера от этого сносит крышу при попытке преобразовать интерфейс к IStream. Вот где ад и Палестина. А описанное в статье, это так, семечки.
Да согласен, что это не самое сложное.

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

Основные источники: codeproject, stackoverflow и msdn. И если там попытаться найти что-то о способах маршализации каких-то типов, то это только разрозненные Q&A, где даже не всегда есть нормальный ответ.
Сам собой встаёт вопрос, почему бы было не использовать unsafe {}? Когда нужно промаршалить сложные структуры туда-обратно, я всегда пишу полностью управляемый аналог неуправляемых структур, а потом «маршалю» содержимое копированием в/из неуправляемых структур. Также производительность при этом на 20-50% выше, чем при использовании встроенного маршалинга.
Спасибо за ссылку. Как раз выше обсуждалась эта тема.
>Все чаще перед разработчиками стала вставать задача вызова native методов из managed кода.

улыбнуло:)
Sign up to leave a comment.

Articles