with parameter method ejemplos c# pinvoke

parameter - ref c#



¿Cuál es la diferencia entre[In, Out] y ref cuando se usa pinvoke en C#? (1)

¿Hay alguna diferencia entre usar [In, Out] y solo usar ref al pasar parámetros de C # a C ++?

He encontrado un par de publicaciones SO diferentes, y también algunas cosas de MSDN que se acercan a mi pregunta pero que no responden del todo. Supongo que puedo usar de forma segura la referencia al igual que usaría [In, Out], y que el comisario no actuará de manera diferente. Mi preocupación es que actuará de manera diferente y que C ++ no estará contento con la aprobación de mi estructura C #. He visto ambas cosas en el código base en el que estoy trabajando ...

Aquí están las publicaciones que he encontrado y que he estado leyendo:

¿Los atributos P / Invoke [In, Out] son ​​opcionales para calcular matrices? Me hace pensar que debería usar [In, Out].

Estas tres publicaciones me hacen pensar que debería usar [In, Out], pero que puedo usar ref en su lugar y tendrá el mismo código de máquina. Eso me hace pensar que estoy equivocado, por lo tanto preguntar aquí.


El uso de ref o out no es arbitrario. Si el código nativo requiere paso por referencia (un puntero), entonces debe usar esas palabras clave si el tipo de parámetro es un tipo de valor. Para que el jitter sepa generar un puntero al valor. Y debe omitirlos si el tipo de parámetro es un tipo de referencia (clase), los objetos ya son punteros debajo del capó.

Los atributos [In] y [Out] son ​​necesarios para resolver la ambigüedad acerca de los punteros, no especifican el flujo de datos. [In] siempre está implícito por el agente de código de Pinvoke, por lo que no tiene que ser expresado explícitamente. Pero debe usar [Out] si espera ver los cambios realizados por el código nativo a una estructura o miembro de clase en su código. Pinshoke Marshaler evita copiar de forma automática para evitar el gasto.

Otra peculiaridad entonces es que [Out] no es a menudo necesario. Ocurre cuando el valor es blittable , una palabra costosa que significa que el valor administrado o el diseño del objeto es idéntico al diseño nativo. El agente de cálculo de pinvoke puede tomar un atajo, fijar el objeto y pasar un puntero al almacenamiento de objetos administrado. Entonces, inevitablemente verá cambios, ya que el código nativo está modificando directamente el objeto administrado.

Algo que en general quieres perseguir, es muy eficiente. Usted ayuda al darle al tipo el atributo [StructLayout (LayoutKind.Sequential)], suprime la optimización que usa el CLR para reorganizar los campos para obtener el objeto más pequeño. Y al usar solo campos de tipos de valor simples o búferes de tamaño fijo, aunque no siempre tiene esa opción. Nunca use un bool , use byte en su lugar. No hay una manera fácil de averiguar si un tipo es blittable, aparte de que no funciona correctamente o usando el depurador y comparar los valores de puntero.

Solo sea explícito y siempre use [Out] cuando lo necesite. No cuesta nada si resulta que no es necesario. Y es autodocumentada. Y puede sentirse bien de que aún funcione si cambia la arquitectura del código nativo.