remarks net generate example c# .net com com-interop

c# - generate - Pase un búfer de caracteres de.NET a COM y vuelva a actualizarlo



params comments c# (1)

Bueno, ciertamente es una función difícil de llamar correctamente. Su declaración es más o menos correcta, solo necesita aplicar el atributo [PreserveSig] y hacer que el valor de retorno escriba int para que pueda descubrir un valor de retorno S_FALSE que indica que no hay un elemento siguiente.

La dificultad está en tener que adivinar por adelantado qué tan grande debe pasar StringBuilder. El código nativo recibe un puntero sin formato en el montón del GC, apuntando al buffer del constructor, por lo que los accidentes son bastante fatales. Debe adivinar de antemano en una Capacidad adecuada para el constructor y pasarlo como el argumento inicial de pcch .

El Marshaller presta atención al SizeParamIndex después de que la función regrese. Solo copiará tantos caracteres como indica ppch . Si por alguna razón escribe más de lo que cabe en el búfer, el programa abortará instantáneamente con ExecutionEngineException, ya que eso indica que el montón de GC estaba dañado.

Tenga en cuenta que si adivina una Capacidad que es demasiado baja, entonces no necesariamente puede descubrir esto. Puede obtener una cadena truncada cuando la función copia solo tantos caracteres que se ajustan y no devuelve un código de error. La mejor manera de averiguar si eso es un problema es simplemente probar esto y pasar intencionalmente un pequeño generador. Presta atención al valor de retorno.

Vale la pena señalar una peculiaridad, la firma de la función golpea en un truco que era común en los primeros días de COM, en realidad devolvía datos binarios en lugar de texto a través del OLECHAR *. Fuerte sugerencia, ya que no se garantiza que la cadena termine en cero. Esto no tendrá un buen final en .NET, los datos se corromperán cuando la cadena se normalice. Y bloquee su programa cuando los datos coincidan con uno de los caracteres subrogantes utf-16. Si ese es el caso, entonces necesitas un corto [] en lugar de un StringBuilder.

Tengo que llamar al siguiente método COM desde C #, que devuelve una cadena en el búfer provisto pchText (que no necesariamente termina en cero) y el número de caracteres copiados en pcch :

HRESULT Next([in, out] long* pcch, [out, size_is(*pcch)] OLECHAR* pchText);

¿Cómo defino la firma de C # para la interoperabilidad?

Hasta ahora, he intentado esto:

void Next(ref int pcch, [MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 0)] System.Text.StringBuilder pchText);

Parece que funciona, pero no estoy seguro de si SizeParamIndex tiene algún efecto sobre StringBuilder .