Передайте строку в аргумент Syscall в Go - PullRequest
1 голос
/ 17 февраля 2020

Я хотел бы использовать функцию C, скомпилированную в DLL. Вот функция C, которую я хотел бы использовать:

int setProxy(const proxy_config* p_proxy);

Требуется постоянный указатель на структуру C, определенную следующим образом:

typedef struct
{
    char *host_address; 
    int port;           
    char *username;     
    char *password;     
} proxy_config;

Для этого Я преобразовал эту C_structure в Go эквивалент следующим образом:

type proxy_configuration struct {
    host_address *uint16 
    port int             
    username *uint16     
    password *uint16     
}

Для преобразования строк я использую следующую функцию:

func StringToCString(s string) (*uint16, error) {
    for i := 0; i < len(s); i++ {
        if s[i] == 0 {
            return nil, errors.New("Problem with the string : "+s)
        }
    }
    p := utf16.Encode([]rune(s + "\x00"))

    return &p[0], nil
}

Затем я вызываю ее:

import (
    "syscall"
    "unsafe"
)

func SetProxy(host_address string, port int, username string, password string) error {

    [...Conversion code from Go string to Struct...]

    var nargs uintptr = 1
    ret, _, callErr := syscall.Syscall(
        uintptr(setProxy), 
        nargs,
        uintptr(unsafe.Pointer(&proxy)), 
        0,
        0,
    )
}

, где setProxy - результат syscall.GetProcAddress(DLL,"setProxy")

Проблема в том, что, когда я просматриваю журналы, сгенерированные DLL, все *uint16 содержат только один символ, а не вся строка, тогда как порт содержит хорошую информацию.

Таким образом, мой вопрос:

Как передать целые строки в параметрах Syscall, а не только в первом символ?


РЕДАКТИРОВАТЬ

Если я изменю return &p[0], nil в StringToCString на return &p[i], nil, я получу i-й символ строки. .. Так что проблема определенно есть, я просто знаю, как ее исправить ...

1 Ответ

3 голосов
/ 17 февраля 2020

Передать строку в аргумент Syscall в Go

Как передать целые строки в параметрах [Windows] Syscall?


Очевидный ответ - взглянуть на стандартные библиотеки Go, которые создают множество системных вызовов Windows.


package windows

golang.org/x/sys/windows

fun c UTF16FromString

func UTF16FromString(s string) ([]uint16, error)

UTF16FromString возвращает кодировку UTF-16 строки UTF-8 с добавлением завершающего NUL. Если s содержит байт NUL в любом месте, он возвращает (nil, syscall.EINVAL).

fun c UTF16PtrFromString

func UTF16PtrFromString(s string) (*uint16, error)

UTF16PtrFromString возвращает указатель на кодирование UTF-16 строки s UTF-8 с добавлением завершающего NUL. Если s содержит байт NUL в любом месте, он возвращает (nil, syscall.EINVAL).

fun c UTF16ToString

func UTF16ToString(s []uint16) string

UTF16ToString возвращает UTF -8 кодирование последовательности UTF-16 с удаленным завершающим NUL.

...