【问题标题】:Xamarin binding C library params not working (variadic functions)Xamarin 绑定 C 库参数不起作用(可变参数函数)
【发布时间】:2020-12-13 11:45:34
【问题描述】:

我需要使用一个 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 绑定吗?

来源在githubsphinxbase使用c库

【问题讨论】:

    标签: objective-c xamarin.ios objective-sharpie xamarin-binding


    【解决方案1】:

    这似乎是 arm64 架构的预期行为,因为调用 arm64 函数的方式。

    在最后调用 arm64 库中使用 ...) 的函数时,您必须考虑到前 8 个参数点用于“普通”参数,然后可以选择启动变量/参数。

    因此,在我的示例中,我使用了 5 个 NULL 值来填充前 8 个参数点,然后开始为 ...)

    查看完整答案: https://github.com/xamarin/xamarin-macios/issues/10285

    【讨论】:

      猜你喜欢
      • 2012-03-07
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      相关资源
      最近更新 更多