Przejdź do treści
MQL5 · MetaTrader 5 · po polsku
kod odczarowany

MQL5 / Inżynieria

Import DLL: Unicode kontra ANSI

Łańcuchy MQL5 są szerokoznakowe, a połowa funkcji WinAPI oczekuje bajtów. Kto odpowiada za bufor i skąd biorą się krzaki.

1 fragment kodu z tej strony przeszedł przez kompilator MetaEditor build 6090, 2026-08-05.

MQL5 to potężne narzędzie, ale czasami musi wyjść poza swoją piaskownicę (sandbox). Importowanie funkcji z zewnętrznych bibliotek DLL (zwłaszcza systemowego WinAPI z user32.dll czy kernel32.dll) pozwala na tworzenie zaawansowanych interfejsów, powiadomień i integracji. Jednak to właśnie tutaj programiści C++ i C# zapominają o najważniejszej różnicy: MQL5 wewnętrznie przechowuje stringi jako Unicode (UTF-16), podczas gdy wiele funkcji systemowych oczekuje ciągów ANSI (jednobajtowych).

Zarządzanie pamięcią: Kto jest właścicielem bufora?

W językach zarządzanych (C#, Java) string jest obiektem niemutowalnym. W MQL5 string jest tablicą znaków Unicode zakończoną zerem (null-terminated). Kiedy przekazujesz stringa do funkcji DLL jako parametr, przekazujesz wskaźnik do tego bufora w pamięci terminala. Jeśli funkcja DLL ma go modyfikować (np. pobierać tekst z okna systemowego), MQL5 musi z góry wiedzieć, jak duża jest ta pamięć. W przeciwnym razie DLL nadpisze pamięć sąsiednich zmiennych, powodując критический błąd (Access Violation) i natychmiastowe zamknięcie terminala.

Import DLL: Unicode kontra ANSIŁańcuchy MQL5 są szerokoznakowe, a połowa funkcji WinAPI oczekuje bajtów. Kto odpowiada za bufor i skąd biorą się krzaki. Kopiowanie pamięci: MQL5 (Unicode) vs WinAPI ANSI Bufor MQL5 (UTF-16) T 0x54 0 E 0 Każdy znak = 2 bajty Oczekiwane przez DLL (ANSI) T 0x54 E 0x45 0 Każdy znak = 1 bajt Konwersja! Przekazanie bufora UTF-16 bezpośrednio do funkcji ANSI odczyta połowę znaków jako zera (null).

Wzorzec bezpiecznego wywołania: GetWindowText

Rozważmy klasyczny przykład: chcemy pobrać tytuł okna terminala za pomocą API Windows. Funkcja GetWindowText występuje w dwóch wersjach: GetWindowTextA (ANSI) i GetWindowTextW (Unicode). Użycie wersji "W" (Wide) wydaje się naturalne dla MQL5, ale wymaga ostrożności z buforem. Jeśli użyjemy wersji ANSI, MQL5 niejawnie przekonwertuje stringa, ale musimy zadeklarować parametr odpowiednio.

// Import funkcji systemowej (Unicode)
#import "user32.dll"
   int GetWindowTextW(int hWnd, string &lpString, int nMaxCount);
#import

string GetTerminalTitle() {
    // 1. Inicjalizujemy pusty string o z góry zdefiniowanej długości!
    // Jeśli tego nie zrobimy, string ma długość 0 i DLL nadpisze pamięć.
    string title = " "; 
    StringInit(title, 256); // Alokujemy 256 znaków (512 bajtów w UTF-16)
    
    // Pobieramy uchwyt okna (skrócone, w realu używa się FindWindowW)
    int hwnd = (int)ChartGetInteger(0, CHART_WINDOW_HANDLE);
    
    // 2. Wywołujemy DLL. Zwróć uwagę na operator & (referencja).
    // Musimy przekazać rozmiar w ZNAKACH, nie w bajtach.
    int copied = GetWindowTextW(hwnd, title, 256);
    
    if(copied > 0) {
        // 3. Odczytujemy wartość. MQL5 automatycznie ucięta stringa 
        // na pierwszym znaku null (0x00 0x00).
        return title;
    }
    return "Nie udało się pobrać tytułu.";
}