Массив структуры, переданный из кода C # в C - PullRequest
0 голосов
/ 03 февраля 2019

Я передал массив структур из C # (управляемый код) в C (неуправляемый код).Память структуры расположена в C # end.Массив заполняется в коде C.Мой код многопоточный.Заполнение массива выполняется одним потоком, а другой поток считывает уже заполненные элементы из массива struct.Но я не могу прочитать данные из второго потока, пока первый поток не выйдет, однако память совместно используется обоими.

Пример кода

C # struct

public struct Data
{
    public IntPtr str;

    [MarshalAs(UnmanagedType.I4)]
    public int id;
}

Выделениепамять массива структуры на стороне C #

GCHandle[] handles = new GCHandle[10];

for (int i = 0; i < 10; i++)
{
     _data[i] = new Data();
     byte[] bd = new byte[100];
     handles[i] = GCHandle.Alloc(bd, GCHandleType.Pinned);
     data[i].str = handles[i].AddrOfPinnedObject();
}

Первый поток передает этот массив _data структуры в неуправляемый код (код C) для заполнения с использованием func

void func([In,Out] Data[] _data);

Второй поток начинает читать заполненную структуруданные, но все же первый поток заполняет данные для индекса остатка.В этом случае данные доступны для _data[0].str, но _data[0].id показывает 0, но в конце C он показывает правильное заполненное значение, т. Е. 5. Пожалуйста, помогите, почему приходят данные для члена структуры int id 0. Только правильное значение приходитпосле окончания первого потокаНо так как память распределяется, она должна быть доступна, как только она заполнена неуправляемым кодом.

Любая помощь будет высоко оценена.

Я хочу, даже если поток 1 не делаетКонец потока 2 должен иметь возможность извлекать значения индексов, которые уже заполнены неуправляемым кодом.

1 Ответ

0 голосов
/ 03 февраля 2019

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

Решение - использовать адрес массива напрямую с небезопасным кодом.

extern void func(Data* data);

fixed(Data* p = _data)
{
    func(p);
}

Если вам не нравится небезопасный код, так как память структурного массива является последовательной, вы можете передать ссылку на 1-й элемент.Но я не уверен, что это достаточно безопасно.

extern void func(ref Data data);

func(ref _data[0]);
...