Marshaling Char *. Как получить всех персонажей - PullRequest
2 голосов
/ 08 февраля 2011

Я пытаюсь создать оболочку .net для настраиваемого COM-интерфейса.

Интерфейс определяется следующим образом в C ++:

DECLARE_INTERFACE_(IDumpAsf, IUnknown)
{
    STDMETHOD(get_UserParams) (THIS_
                int *is_auto_start,
                int *fileSize,         
                int *packetSize,
                char *baseName, 
                char *filePath
             ) PURE;

    STDMETHOD(set_UserParams) (THIS_
                int is_auto_start,
                int fileSize,          
                int packetSize,
                char *baseName, 
                char *filePath
             ) PURE;

    STDMETHOD(enable_Run) (THIS_
                bool is_run
             ) PURE;
};

И я объявил интерфейс какэто в C #:

public interface IDumpASF
{

    [PreserveSig]
    int get_UserParams(
        [Out] out int is_auto_start,
        [Out] out int fileSize,
        [Out] out int packetSize,
        [Out] out System.Sbyte baseName,
        [Out] out System.SByte filePath
        );

    [PreserveSig]
    int set_UserParams(
        [In] int is_auto_start,
        [In] int fileSize,
        [In] int packetSize,
        [In] string baseName,
        [In] string filePath
        );

    [PreserveSig]
    int enable_Run([In] bool a);

}

Пример использования таков:

int is_auto_start;
int fileSize;
int packetSize;
SByte baseName;
SByte filePath;

IDumpASF dump = (IDumpASF)asfWriter;

dump.get_UserParams(out is_auto_start, out fileSize, out packetSize, out baseName, out filePath);

Я могу собрать и запустить душ, но я не понимаю, какПредположим, чтобы получить все символы для baseName и filePath.Когда я посылаю SByte, он возвращает первый символ, но как мне получить остальные?Я пробовал несколько других типов, таких как Sbyte [], String, StringBuilder и IntPtr.Всякий раз, когда я пытаюсь преобразовать их в строку, я получаю AccessViolationException.

Могу поспорить, есть кое-что глупое, что я пропустил, но мои пациенты здесь истощаются.

Любая помощь будет очень ценной!

-Svein

Ответы [ 2 ]

2 голосов
/ 08 февраля 2011

Вы должны объявить аргумент как StringBuilder, не используйте out .Обязательно инициализируйте построитель строк, который вы передаете правильно, вы должны установить его Capacity достаточно высоким, чтобы этот нативный код не мог уничтожить кучу мусора.Исправление кода COM будет чем-то, что следует учитывать, так как это в корне небезопасно, поэтому на самом деле следует использовать BSTR.

0 голосов
/ 09 февраля 2011

Спасибо за ответ.После еще нескольких проб и ошибок я, наконец, получил правильную настройку.Как вы сказали, я должен использовать StringBuilder без [Out].Моя проблема заключалась в том, что ценности, которые я получил, не имели особого смысла.В дополнение к тому, что вы сказали мне, мне также пришлось указать, как упорядочить значение с помощью атрибута MarshalAs.

Большое спасибо за помощь!

Вот так выглядит тестовый класс:

System.Text.StringBuilder baseName = new System.Text.StringBuilder(256);
System.Text.StringBuilder filePath = new System.Text.StringBuilder(256);

EncirisWrapper.IDumpASF dump = (EncirisWrapper.IDumpASF)asfWriter;

dump.get_UserParams(out is_auto_start, out fileSize, out packetSize, baseName, filePath);

А вот так выглядит оболочка:

[PreserveSig]
int get_UserParams(
   [Out] out int is_auto_start,
   [Out] out int fileSize,
   [Out] out int packetSize,
   [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder baseName,
   [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder filePath    
   );

-Svein

...