Experiencia de escalada: problemas encontrados por C# llamando a C++ DLL (LoadLibrary)

Lo que sucedió: los dos proyectos de .net core y .net framework han estado usando el método LoadLibraryA para cargar Dlls, y luego, inexplicablemente, hay comentarios de los usuarios de que la función es anormal.

La forma anterior de escribir:
use LoadLibraryA
La forma revisada de escribir:
use LoadLibrary

Resumen personal: no tenía muy claro el concepto de caracteres anchos y multicaracteres, así como LoadLibrary, LoadLibraryA y LoadLibraryW, lo que llevó a escribir mal el código de llamada.

Resumen de conocimientos:

  1. LoadLibrary y LoadLibraryA son en realidad la misma función, solo un alias entre las versiones ANSI (LoadLibraryA) y Unicode (LoadLibraryW). Windows elige automáticamente cuál usar en función de sus definiciones de macro.

  2. De forma predeterminada, la codificación de caracteres de Windows es Unicode, por lo que LoadLibrary llama de forma predeterminada a LoadLibraryW, la versión de caracteres anchos.

  3. Si su nombre de ruta DLL contiene solo caracteres ASCII, puede usar LoadLibraryA de manera segura. De lo contrario, debe usar LoadLibrary, que irá a la función correcta según su definición de macro.

Si realmente necesita llamar a estas API, puede usarlas así en C#:

using System.Runtime.InteropServices;

public class Win32Native {
    
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr LoadLibrary(string libname);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool FreeLibrary(IntPtr hModule);
}

En este ejemplo, CharSet = CharSet.Autose le indica al tiempo de ejecución que elija automáticamente entre LoadLibraryA o LoadLibraryW.

4. En .NET Core y .NET Framework, las cadenas utilizan la codificación Unicode de forma predeterminada. Cada carácter del tipo de cadena (cadena) utiliza una codificación de caracteres Unicode de 16 bits (2 bytes) de forma predeterminada. Entonces podemos decir que el valor predeterminado es la codificación de caracteres anchos.

Este comportamiento es independiente del tipo de proyecto creado (como WPF, ASP.NET, aplicación de consola, etc.), es una característica del lenguaje C# y el tiempo de ejecución de .NET. No utiliza los conceptos de caracteres anchos y multibyte en C++.

5... En .NET Core o .NET Framework, si necesita cargar y usar archivos DLL de C++, deberá usar P/Invoke (Servicios de invocación de plataforma) para llamar al código no administrado. Para la función LoadLibrary, puede usarla de la siguiente manera:

using System.Runtime.InteropServices;

public class Win32Native {
    
    
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr LoadLibrary(string libname);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool FreeLibrary(IntPtr hModule);
}

Este DllImportes el método que utiliza .NET para declarar la DLL no administrada que se va a llamar. CharSet = CharSet.UnicodeDígale al tiempo de ejecución que espera la versión Unicode de la función (es decir, LoadLibraryW), esto se debe a que .NET usa la codificación de caracteres Unicode de manera predeterminada.

Por lo tanto, en el entorno .NET, debe usar LoadLibrary directamente y establecer CharSet = CharSet.Unicode, en lugar de usar LoadLibraryA o LoadLibraryW.

6. La codificación de caracteres anchos y la codificación de varios bytes son dos tipos de codificación de caracteres, que se utilizan principalmente al procesar caracteres. Estos dos métodos de codificación se utilizan principalmente para tratar entornos multilingües, ya que diferentes idiomas pueden requerir diferentes números de bytes para representar un carácter.
Codificación de caracteres anchos : la codificación de caracteres anchos es un esquema de codificación de caracteres de longitud fija. En este esquema, cada carácter se representa utilizando el mismo número de bytes. Por ejemplo, UTF-16 y UTF-32 son codificaciones de caracteres amplios donde cada carácter usa 2 bytes y 4 bytes respectivamente. La ventaja de este esquema de codificación es que es fácil de procesar y analizar porque cada carácter tiene una longitud fija. Sin embargo, esto también puede generar espacio desperdiciado, ya que algunos caracteres pueden no requerir tantos bytes para ser representados. Codificación multibyte : la codificación multibyte es un esquema de codificación de caracteres de longitud variable. En este esquema, los caracteres pueden estar representados por uno o más bytes. Por ejemplo, UTF-8 es una codificación de varios bytes en la que un carácter se puede representar de 1 a 4 bytes. La ventaja de este esquema de codificación es la eficiencia de espacio, ya que puede representar un carácter utilizando el número mínimo de bytes necesarios. Sin embargo, manejar y analizar caracteres en esta codificación puede ser más complicado porque cada carácter tiene una longitud variable. En un entorno de programación multilingüe, la codificación UTF-8 suele ser el esquema de codificación preferido porque es compatible con ASCII y puede manejar caracteres de varios idiomas de manera eficiente.

Si el artículo está mal, ¡bienvenido a corregirme!

Supongo que te gusta

Origin blog.csdn.net/weixin_38428126/article/details/131409609
Recomendado
Clasificación