Маршалинг двумерного массива символов фиксированной длины C++ в качестве члена структуры

Я пытаюсь вызвать неуправляемую функцию С++, которая имеет структуру в качестве входного параметра. Структура определяется в заголовочном файле следующим образом:

struct MyStruct
{
int     siOrder;
char     aaszNames[6][25];
int     siId[6];
int     siTones[6];        
};

Я попытался объявить управляемую структуру следующим образом:

[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct MyStruct {

public int siOrder;

[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst=150)]
public string aaszNames;

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=6, ArraySubType=UnmanagedType.I4)]
public int[] siId;

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=6, ArraySubType=UnmanagedType.I4)]
public int[] siTones;
}

Но без особого успеха. Я предполагаю, что маршалинг терпит неудачу, поскольку aaszNames на самом деле представляет собой массив из шести 25 длинных строк, заканчивающихся нулем. Я попытался объявить aaszNames как

 [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=150)]
 public char[] aaszNames;

заполнение массива нулями там, где это необходимо. Но, опять же, ничего.

Есть ли что-то, что мне не хватает? Что я не так? Каков наилучший способ маршалирования этого двумерного массива символов?

Любые подсказки, пожалуйста.


person TTheot    schedule 15.02.2010    source источник
comment
Совсем не похоже на С++...   -  person Matthieu M.    schedule 15.02.2010
comment
Он хочет вызвать функцию C++ из C#.   -  person Johannes Schaub - litb    schedule 15.02.2010
comment
Я добавил тег C#, чтобы, надеюсь, было понятнее, что имеется в виду. Я также думал, что это вопрос чистого С++, пока не добрался до кода.   -  person Yacoby    schedule 15.02.2010
comment
Я думаю, Матье говорит, что ваш неуправляемый код скорее похож на C, и предлагает использовать std::string или что-то подобное в C++?   -  person Nikola Gedelovski    schedule 15.02.2010
comment
да, я согласен, что это довольно похоже на C, но это сторонняя dll, с плохой документацией, ссылающейся на нее как на dll C ++ ... Не могу ничего сделать, чтобы изменить эту dll.   -  person TTheot    schedule 15.02.2010
comment
вы когда-нибудь находили решение этой проблемы? У меня похожая проблема, я не могу заставить атрибут marshalas работать со значениями, такими как ваш siId или siTones.   -  person calvin    schedule 02.03.2010
comment
@TTheot Вы помните решение вышеизложенного :)   -  person Boomer    schedule 19.09.2013


Ответы (4)


Попробуйте использовать несколько структур C#:

[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct MyStruct_Name
{
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 25)]
    public string name;
}

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyStruct
{
    public int siOrder;

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6)]
    public MyStruct_Name aaszNames;

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I4)]
    public int[] siId;

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I4)]
    public int[] siTones;
}

Вот как я передавал массивы строк в стиле C.

Не забудьте создать содержимое aaszNames! Маршаллер ненавидит нулевые ссылки.

MyStruct foo = new MyStruct();
for (int i = 0; i < 6; i++)
{
    foo.aaszNames[i] = new MyStruct_Name();
    foo.aaszNames[i].name = "";
}

Удачи!

person Michael Miller    schedule 22.08.2011

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=150)]
 public char[] aaszNames;

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

person necrostaz    schedule 15.02.2010
comment
Функция, которую я вызываю, имеет в качестве параметра еще одну структуру, с которой у меня нет проблем. Что именно вы имеете в виду под плохим распределением памяти? - person TTheot; 15.02.2010
comment
1. Как вы выделяете память для своей структуры? 2. Лучшим способом использования структуры маршала в качестве параметра входной функции является указатель (IntPtr). Типичный пример: IntPtr strPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(StructType))); Marshal.StructureToPtr(struct,strPtr); Фу(стрПтр); Маршал.FreeHGlobal(strPtr); - person necrostaz; 15.02.2010
comment
Я действительно не выделяю память вручную. Я знаю об этом примере, но поскольку мне удалось успешно передать другую (более простую) структуру в качестве входного параметра в той же функции и в нескольких других, я подумал, что оставить это для .NET также будет работать. - person TTheot; 15.02.2010

Я бы написал небольшую программу на языке C, чтобы проверить размер C-структуры в байтах.
Затем я бы пошел с другим предложением, чтобы извлечь поле данных за полем.
С точки зрения C, /0 обрабатывается как обычный символ, включенный в 6 байтов, тогда как C# будет использовать длину 5 и скрывать /0.

person weismat    schedule 16.02.2010

char aaszNames[6][25];

char типа С++ - 8 бит~

но char типа С# - это Unicode (16 бит)!

так char типа C++ ‹-> byte типа C#

person Joe    schedule 15.06.2011