Xamarin 绑定 C 库参数不起作用(可变函数)
Xamarin binding C library params not working (variadic functions)
我需要使用 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 - 默认参数不起作用:
当我对 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 库(我可以用 C 函数中的 E_INFO 函数检查)。
有人知道如何使用参数或不使用 5 个前缀空值来使此 Xamarin C 绑定正确吗?
来源已开启 github
在 sphinxbase
使用 c 库
由于调用 arm64 函数的方式,这似乎是 arm64 架构的预期行为。
最后调用 arm64 库中使用 ...) 的函数,您必须考虑前 8 个参数点用于 'normal' 个参数,然后是可选的 variable/params可以开始了
因此,在我的示例中,我使用了 5 个 NULL 值来填充前 8 个参数点,然后开始为 ...)
查看完整答案:
https://github.com/xamarin/xamarin-macios/issues/10285
我需要使用 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 - 默认参数不起作用:
当我对 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 库(我可以用 C 函数中的 E_INFO 函数检查)。
有人知道如何使用参数或不使用 5 个前缀空值来使此 Xamarin C 绑定正确吗?
来源已开启 github 在 sphinxbase
使用 c 库由于调用 arm64 函数的方式,这似乎是 arm64 架构的预期行为。
最后调用 arm64 库中使用 ...) 的函数,您必须考虑前 8 个参数点用于 'normal' 个参数,然后是可选的 variable/params可以开始了
因此,在我的示例中,我使用了 5 个 NULL 值来填充前 8 个参数点,然后开始为 ...)
查看完整答案: https://github.com/xamarin/xamarin-macios/issues/10285