Маршалинг массива структур от C++ до C#?

Если Вы хотите видеть css значения по умолчанию для Firefox, искать файл, названный 'html.css' в распределении (должны быть некоторые другие полезные css файлы в том же каталоге). Вы могли выбрать правила, что Вы хотите и применяете их после сброса.

кроме того, стандарт CSS2 имеет демонстрационная таблица стилей для html 4.

5
задан fretje 13 May 2011 в 11:42
поделиться

5 ответов

Я не могу воспроизвести вашу проблему, что заставляет меня подозревать, что она действительно связана с C ++. Вот полный исходный код моей попытки.

dll.cpp - скомпилировать с помощью cl.exe /LD[1112708 sizes:[1288 sizestest.cs - скомпилировать с csc. exe / platform: x86 :

using System;
using System.Runtime.InteropServices;


[StructLayout(LayoutKind.Sequential)]  
public class MyStruct
{
  [MarshalAsAttribute(UnmanagedType.LPStr)]
  public string _id;
  [MarshalAsAttribute(UnmanagedType.LPStr)]
  public string _description;
}


class Program
{
    [DllImport("dll")]
    static extern IntPtr get_my_structures();

    static void Main()
    {
        int structSize = Marshal.SizeOf(typeof(MyStruct));
        Console.WriteLine(structSize);

        IntPtr myStructs = get_my_structures();
        for (int i = 0; i < 3; ++i)
        {
            IntPtr data = new IntPtr(myStructs.ToInt64() + structSize * i);
            MyStruct ms = (MyStruct) Marshal.PtrToStructure(data, typeof(MyStruct));

            Console.WriteLine();
            Console.WriteLine(ms._id);
            Console.WriteLine(ms._description);
        }
    }
}

Это правильно распечатывает все 3 структуры.

Можете ли вы показать свой код C ++, который заполняет структуры? Тот факт, что вы можете вызывать его напрямую из C ++ и получать правильные результаты, не обязательно означает, что это правильно. Например, вы могли возвращать указатель на структуру, размещенную в стеке. Тогда при прямом вызове вы получите технически недействительный указатель, но данные, скорее всего, останутся сохраненными. При выполнении маршаллинга P / Invoke, стек может быть перезаписан структурами данных P / Invoke в момент попытки считывания значений оттуда.

3
ответ дан 15 December 2019 в 01:04
поделиться

Я бы изменил структуру. Вместо строк и т. Д. Используйте IntPtr:

[StructLayout(LayoutKind.Sequential)]  
public class MyStruct
{
  private IntPtr _id;
  private IntPtr _description;
}

Затем каждое значение массива C # можно вручную упорядочить в строку с помощью Marshal.PtrToString с учетом кодировки и т. Д.

1
ответ дан 15 December 2019 в 01:04
поделиться

Обычно я решаю эти вещи методом проб и ошибок. Убедитесь, что для StructLayout установлено свойство CharSet, и я бы попробовал UnmanagedType.LPTStr, кажется, лучше работает для char *, хотя я не уверен, почему.

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]  
public class MyStruct
{
    [MarshalAsAttribute(UnmanagedType.LPTStr)]
    private string _id;
    [MarshalAsAttribute(UnmanagedType.LPTStr)]
    private string _description;
}
0
ответ дан 15 December 2019 в 01:04
поделиться

Я также думаю, что в дополнение к приведенным ответам вам также необходимо указать длину, т.е. [MarshalAsAttribute (UnmanagedType.LPTStr), SizeConst =, ArraySubType = System.Runtime.InteropServices.UnmanagedType.AnsiBStr)]

Это метод проб и ошибок, чтобы получить это право, а также еще одна вещь, которую следует учитывать в некоторых вызовах WinAPI, которые ожидайте строковый параметр, обычно это параметр ref, возможно, стоит попробовать и класс StringBuilder ... По этому поводу ничего не приходит на ум, кроме пунктов, которые я здесь упомянул ... Надеюсь, это поможет, Том

0
ответ дан 15 December 2019 в 01:04
поделиться

Вы должны использовать UnmanagedType.LPTStr для char *. Также StringBuilder рекомендуется для не const char *: И спецификация CharSet:

[StructLayout(LayoutKind.Sequential, Charset = CharSet.Auto)]  
public class MyStruct
{
  [MarshalAsAttribute(UnmanagedType.LPTStr)]
  private StringBuilder _id;
  [MarshalAsAttribute(UnmanagedType.LPTStr)]
  private StringBuilder _description;
}

Что касается объявления DllImport, вы пробовали

[DllImport("legacy.dll", EntryPoint="get_my_structures")]
public static extern MarshalAs(UnmanagedType.LPArray) MyStruct[] GetMyStructures();

?

Кроме того, если предыдущее не работает, оставьте его в IntPtr и попробуйте Машалировать возвращенные структуры следующим образом:

for (int i = 0; i < structuresCount; i++)
{
    MyStruct ms = (MyStruct) Marshal.PtrToStructure(myStructs, typeof(MyStruct));
    ...
    myStructs += Marshal.SizeOf(ms);
}
0
ответ дан 15 December 2019 в 01:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: