Pull to refresh

Comments 24

Вы не поверите, я вчера весь день головой об стенку, писал класс-враппер к dll. А сегодня на Вы выложили ОТЛИЧНЫЕ примеры, опоздав всего на день =)
Методы работы с неупраляемым кодом:
— кнутом,
— пряником,
— уволить.
Отлично… Я думаю еще пригодилось бы: запуск CLR из неуправляемого, кодогенерация управляемого из неуправляемого и было бы полезным что-то типа boost шалонов по работе с управляемым из неуправляемого :)
Вы свой код отлаживали? Вместо [StructLayout(LayoutKind.Sequential)] надо [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)].

Впрочем какая отладка, «public char[] str;;» даже не компилируется…
Среда автоматически использует однобайтные символы, если библиотека не поддерживает Unicode, но если этого не происходит, то да — необходимо будет ручками указывать в аттрибуте.

Код проверял и отлаживал в Visual Studio 2005, в понедельник могу выложить весь исходный код обоих тестовых проектов.

На основе этого же принципа, в другом нашем коммерческим продукте, у меня работает вызов библиотеки, структура которой описана в нескольких тысячах строк, используются массивы до 4 уровня многомерности. Передача char[] работает, как от неё и жду. Пожалуйста проверьте, возможно у вас где-то ошибка, поэтому не можете скомпиллировать
CharSet.Ansi автоматически подставляется для структур только на Windows 98/Me. Что поддерживает unmanaged библиотека .Net Framework узнать никак не может, поэтому выбирает CharSet в зависимости от ОС. Это достаточно ясно написано в документации

If the CharSet field is set to CharSet.Unicode, all string arguments are converted to Unicode characters (LPWSTR) before being passed to the unmanaged implementation. If the field is set to CharSet.Ansi, the strings are converted to ANSI strings (LPSTR). If the CharSet field is set to CharSet.Auto, the conversion is platform dependent (Unicode on Windows NT, Windows 2000, Windows XP, and Windows Server 2003 family; ANSI on Windows 98 and Windows Me).

и подтверждается опытом.

Ошибки никакой у меня нет. Выделенный мной кусок кода «public char[] str;;» гарантированно не компилируется, это можно сказать и наизусть. Две идущие подряд точка с запятой в C# обозначающие пустой statement, в отличие от Си++, не компилируются. Соответственно не ясно откуда вы копировали код.
Вообще-то чарсет «по умолчанию» зависит от компилятора.
В частности, C# по умолчанию использует ANSI.
Спасибо за замечание по поводу Charset, внимания большого этому Charset не уделял, т.к. у нас библиотечка не Unicode
Это не правда и это легко проверить экспериментом.
Вот и убедитесь экспериментально, что это как раз именно так.

    [StructLayout(LayoutKind.Sequential)]
    struct S_NoCharset
    {
      public int a;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    struct S_ForceAnsi
    {
      public int a;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct S_ForceAuto
    {
      public int a;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct S_ForceUnicode
    {
      public int a;
    }


* This source code was highlighted with Source Code Highlighter.




Более того, можете даже открыть для себя атрибут DefaultCharSet, чтобы задать чарсет по умолчанию для всего модуля.
напишите пожалуйста, где можно установить DefaultCharSet в Ansi… сейчас необходимости в этом нет, но чтобы в случае необходимости, мне можно было установить в Unicode, не вписывая в каждый атрибут по-отдельности.
Удалите лишний символ ';', его там быть не должно, как он вкрался не знаю, скорее всего после манипуляций с «разукрашиванием кода» )))
Код вставил из реального тестового проекта, в понедельник размещу и сами исходники, они на рабочем компьютере.

PS: VS 2005 Pro не ругается, 2010 Ultimate тоже не ругается, видимо просто игнорирует опечатку двух идущих подряд символов ';'
есть хороший ресурс на эту тему: www.pinvoke.net/
там много оберток для разных винапишных и не только функций
для WinApi функций, возможно использовать Windows® API Code Pack for Microsoft® .NET Framework. Microsoft не поддерживает этот проект официально, но заявляет, что оно работает, можно юзать Ribbon, новые фичи Windows 7 и другой WinApi
Я считаю, что приведение аналогов кода на C — очень удачная идея. Она позволяет более детально вникнуть в суть происходящего. Надеюсь, в следующих частях этот приём так же будет использоваться.
огромные структуры ref просто не мог

Пример «огромной» структуры в студию!
Добавил запись и часть кода в свой блог, по поводу той «огромной» структуры, на которую CLR ругнулся, сказав, что не может её упаковать… слишком большая для него o_O
Хм… Я готов опустить вопрос целесообразности гонять структуру размером 370 килобайт туда-сюда.
1. Вы пробовали использовать unsafe и просто передавать указатель на структуру? По-моему, это было бы и сильно быстрее, и проще.
2. 370 килобайт — это слишком много для стека (структуры ведь размещаются в стеке). Если объявить ее классом (просто заменить struct на class), чтобы она размещалась в куче, то P/Invoke работает как и положено, причем ее даже не нужно передавать как ref (потому что класс — это автоматически reference тип).
Сложность структуры и её размер да… не айс. Но деваться некуда, я и сам много плевался по этому поводу, но деваться мне дали библиотечку и задание «надо работать» )))
unsafe решили не использовать по ряду трудностей, которые бы они вызвали у нас при работе, да и не хотелось подписывать сборку, как unsafe.

Эта структура только одна часть, другая — динамическая… указатель на массив указателей. Размеры массивов заранее неизвестны, там ни структуры, ни классы не спасут, необходимо ручками выделять и писать в память (подробнее о том, как решил, опишу во 2 части статьи).
М.б. тогда стоило написать Custom Marshaler?
возможно стоило бы… но я не читал про него и не думал о его реализации. Сделал всё на основе стандартных классов (((
Должен заметить что некоторые библиотеки не удаётся удобно использовать из C# ввиду их API,
а точнее структур данных, которые в этом API используются (например Extended MAPI).
И тут напомощь приходит Managed C++ на котором можно написать обёртку с нормальным интерфейсом, а её уже использовать из любого языка для .NET.
C# очень давно руками не трогал, но то что я увидел мне не понравилось
Sign up to leave a comment.

Articles