Могут ли C # структуры из неуправляемого мира быть «живыми» - обновляться? - PullRequest
3 голосов
/ 31 октября 2011

Предположим, я получаю указатель IntPtr на структуру из неуправляемой библиотеки.Есть ли способ, в C #, получить "живую" структуру из этого указателя, так что если я сделаю вызов, который изменяет неуправляемую структуру, моя "живая" структура немедленно отразит это?

Я считаю, чтоСтандартный подход заключается в создании копии данных с использованием маршаллинга, который не может быть «живым», как это, по разным причинам (структура, совместимость типов данных, не находящаяся в управляемой памяти .NET).Но я не смог найти явного подтверждения того, что «живые» структуры невозможны в C #.Это они?

Что мне ближе всего к таким "живым" структурам, не переходя на C ++ / CLI?

Ответы [ 2 ]

3 голосов
/ 31 октября 2011

Попробуйте использовать UnmanagedMemoryStream :

Этот класс поддерживает доступ к неуправляемой памяти с использованием существующей потоковой модели и не требует копирования содержимого в неуправляемой памяти.в кучу.

Это означает, что вы будете искать / читать / сбрасывать поток, но это позволит избежать сортировки.Это все еще не live в том смысле, что вы, вероятно, захотите заключить эти обращения в свойства .NET.

Другая альтернатива: возможно, вы могли бы использовать System.Buffer , после получения неуправляемого указателя.Возможно, вам придется сделать несколько умных заклинаний.

1 голос
/ 31 октября 2011

Технически, вы МОЖЕТЕ создать структуру, данные которой «живы» для изменений, сделанных в другом месте.Тем не менее, вы хотите ОЧЕНЬ тщательно подумать о том, ДОЛЖНЫ ли вы.

По самому определению в C # структура - это «тип значения».Это означает, что один экземпляр - это одно значение, например «5», и любое изменение этого значения концептуально приводит к новому значению.5 + 1 == 6;это не означает, что 5 «становится» 6, когда вы добавляете 1, это означает, что два значения 5 и 1, когда они добавляются, равны 6.

Типы значений в программировании также имеют другую особенность с ссылочными типами;они передаются «по значению», что означает, что они считаются достаточно дешевыми, чтобы «клонировать», когда значение передается в качестве параметра.Любое изменение, которое может быть сделано в значении переменной (или дочерних свойствах) в то время как в методе, отбрасывается, когда вызов завершен, потому что все изменения были внесены в новую копию структуры на верхнем уровне стека, вместо этогоссылки на исходный объект, находящийся ниже в стеке.Вы должны явно переопределить это поведение, используя ключевые слова ref или out, фактически указав, что исходное значение ДОЛЖНО изменяться в зависимости от того, что происходит в методе.

Большинство объектов, реализованных как структуры, заставляют вас обращаться с ними согласнок этим правилам, будучи неизменным;после того, как вы создали его, вы не можете устанавливать его поля / свойства напрямую.Вместо этого вы должны вызывать различные методы для этой структуры, что приведет к созданию новой структуры.

Если вы хотите создать класс, который будет отражать самые последние данные, поступающие с неуправляемой земли, прежде всего я бы сделалэто «класс», так что не возникает путаницы в отношении поведения объекта, когда вы передаете его или пытаетесь изменить его члены.Затем вы в основном создадите «обертку», которая использует вышеупомянутый Kit UnmanagedMemoryStream для получения / установки значений, которые вы выставили в качестве свойств.Это дало бы вам «реактивный» объект, который можно было бы опросить, чтобы получить то, что неуправляемый код установил совсем недавно, а также записать новые значения в правильные места в памяти.Будь очень осторожен;этот код не будет «безопасным» (особенно если вы записываете обратно в него), а зацепка в неуправляемый код с помощью указателей является одним из немногих мест в .NET, где вы можете намеренно завершить работу не только вашей программы и неуправляемой программы C ++,но вся машина.

...