Мне нужно использовать библиотеку 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