Параметры библиотеки C привязки Xamarin не работают (вариативные функции)

Мне нужно использовать библиотеку C, и я легко заставил ее работать на эмуляторе, но на устройстве arm64 только с некоторыми странными хитростями. Проблема в том, что функции C с … (вариативные функции) неправильно передают значения из C# в библиотеку.

Это функция C, с...

cmd_ln_t *
cmd_ln_init(cmd_ln_t *inout_cmdln, const arg_t *defn, int32 strict, ...)
{
va_list args;
const char *arg, *val;
char **f_argv;
int32 f_argc;

va_start(args, strict);
f_argc = 0;
while ((arg = va_arg(args, const char *))) {
    ++f_argc;
    E_INFO("name: %s   ", arg);
    E_INFO(" retrieving value...");
    val = va_arg(args, const char*);
    E_INFO("value retrieved. \n");
    E_INFO("value: %s \n", val);
    if (val == NULL) {
        E_ERROR("Number of arguments must be even!\n");
        return NULL;
    }
    ++f_argc;
}
va_end(args);
.....................................

Я проверяю правильность значений с помощью E_INFO()

Подход 1 — PARAMS по умолчанию не работает:

Когда я использую следующее выражение params по умолчанию для привязок c, «arg», напечатанный в функции, показывает неизвестные символы, а когда используется «val», функция аварийно завершает работу.

[DllImport("__Internal")] public static extern unsafe cmd_ln_t*
cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, params string[] arguments);

Подход 2 — работает более сложный подход:

Когда я использую более сложный подход, все работает, на архитектуре x86_64 нормально, но для arm64 со странным обходным путем. выражение привязки в более сложном подходе.

        [DllImport("__Internal")]
        public static extern unsafe cmd_ln_t* cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, string arg1, string arg2);

        [DllImport("__Internal")]
        public static extern unsafe cmd_ln_t* cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, string arg1, string arg2, string arg3);

        [DllImport("__Internal")]
        public static extern unsafe cmd_ln_t* cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, string arg1, string arg2, string arg3, string arg4);
        //etc etc… for x numbers of arguments

Привязка работает, работает следующий код

            // works for x86_64
            var cmdPointer = MyBindingLib.cmd_ln_init(null, psArgsPointer, 1,
            "-hmm", hmmFolder,
                "-dict", dictFile,
                "-mmap", "no",
                "-kws_threshold", "1e-80", 
                "-lw", "2.0", 
                null);

            // works for arm64
            var cmdPointer = MyBindingLib.cmd_ln_init(null, psArgsPointer, 1,
                null, null,
                null, null, null,
                "-hmm", hmmFolder,
                "-dict", dictFile,
                "-mmap", "no",
                "-kws_threshold", "1e-80",
                "-lw", "2.0", 
                null);

Как видите, x86_64 нормально работает, чтобы получить значения в библиотеку C. Но версия для arm64 должна иметь 5 нулевых значений, другая половина значений не попадет в библиотеку C (я могу проверить это с помощью функции E_INFO в функции C).

Кто-нибудь знает, как правильно настроить эту привязку Xamarin C с параметрами или без нулевых значений префикса 5?

Источник находится на github, использует библиотеку c по адресу sphinxbase


person Toine db    schedule 13.12.2020    source источник


Ответы (1)


Кажется, это ожидаемое поведение для архитектуры arm64 из-за того, как вызываются функции arm64.

Вызов функций в библиотеке arm64, которые используют ...) в конце, вы должны принять во внимание, что первые 8 аргументов предназначены для «обычных» аргументов, затем, необязательно, может начинаться переменная/параметры.

Итак, в моем примере я использовал 5 значений NULL, чтобы заполнить первые 8 полей аргументов, а затем начал значения для ...)

См. полный ответ: https://github.com/xamarin/xamarin-macios/issues/ 10285

person Toine db    schedule 18.12.2020