将 __arglist 与一组不同的命名参数一起使用

发布于 2024-07-11 23:49:13 字数 1095 浏览 9 评论 0原文

在我的应用程序中,我有 2 层。 第一层是 C 遗留的公开 cdecl 函数,这些函数使用“...”语法来表示不同的参数列表。 我发现从 .Net 层(第二层)调用这些函数的唯一方法是使用 DllImport 技术。 例如下面的 C 函数:

int myFunc(char* name, ...);

看起来像 C# 中的那样:

[DllImport("MyDll.dll"),
 CharSet = CharSet.Ansi,
 CallingConvention = CallingConvention.Cdecl]
int myFunc(string name, __arglist);

我的问题是,有时我想使用 2 个额外参数调用此函数,但如果其中一个参数为 NULL,它将不会包含在参数列表中(我的旧代码失败)空值)。 例如,我希望这个调用:

int foo(string name, string a, string b)
{
     myFunc(name, __arglist(a, b));
}

{
     foo("john", "arg1", null);
}

被 C 解释为

myFunc("john", "arg1");

不幸地做了类似的事情:

int foo(string name, string a, string b)
{
     List<string> args = new List<string>();
     if(a != null) args.Add(a);
     if(b != null) args.Add(b);
     myFunc(name, __arglist(args));
}
{
     foo("john", "arg1", null);
}

被 C 解释为:

myFunc(name, args);

而不是:

myFunc(name, args[0]);

有人有任何想法吗?

in my application I have 2 layers. The first layer is a C legacy exposing cdecl functions that use the "..." syntax for a varying parameter list. The only way I found to call these functions from my .Net layer (the second one) is using the DllImport technics. For example the C function below:

int myFunc(char* name, ...);

looks like that in C#:

[DllImport("MyDll.dll"),
 CharSet = CharSet.Ansi,
 CallingConvention = CallingConvention.Cdecl]
int myFunc(string name, __arglist);

My problem is that sometimes I want to call this function with 2 extra parameters but if one of them is NULL it won't be included in the argument list (my legacy code fails on NULL values). For example I want this call:

int foo(string name, string a, string b)
{
     myFunc(name, __arglist(a, b));
}

{
     foo("john", "arg1", null);
}

to be interpreted by C as

myFunc("john", "arg1");

Unfortunately doing something like that:

int foo(string name, string a, string b)
{
     List<string> args = new List<string>();
     if(a != null) args.Add(a);
     if(b != null) args.Add(b);
     myFunc(name, __arglist(args));
}
{
     foo("john", "arg1", null);
}

is interpreted by C like that:

myFunc(name, args);

and not:

myFunc(name, args[0]);

Does anybody have any idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏天碎花小短裙 2024-07-18 23:49:13

C函数如何知道哪一个是最后一个参数? 它无法先验地知道有多少个参数。 它需要额外的信息。 函数获取所需信息的一种常见方法是解析包含的字符串参数以计算格式说明符,如 printf 中所示。 在这种情况下,如果格式字符串仅指示有一个额外参数,则该函数不知道实际上只有一个额外参数的调用与有两个额外参数的调用或有 20 个额外参数的调用之间的区别。函数应该具有只读取一个参数的自律,因为这就是所说的所有格式字符串。 阅读更多会导致未定义的行为。

如果我所描述的不是您的函数的工作方式,那么您在调用端无能为力来解决它。 但是,如果您的函数是这样工作的,那么调用端就无需执行任何操作,因为没有问题。

由于您指出“旧代码在空值上失败”,另一种选择是修复旧代码,使其不再失败。

第三种选择是简单地编写所有四种可能性:

 if (a != null) {
   if (b != null)
     return myFunc(name, a, b);
   else
     return myFunc(name, a);
 } else {
   if (b != null)
     return myFunc(names, b);
   else
     return myFunc(names);
 }

但是,如果有两个以上的可选参数,代码就会开始变得笨拙。

How does the C function know which one is the last parameter? It cannot know a priori how many parameters there are. It needs additional information. One common way for functions get the information they need is by parsing the included string parameter to count format specifiers, as in printf. In that case, if the format string only indicates that there is one extra parameter, then the function doesn't know the difference between a call that really had just one extra parameter and a call that had two or a call that had 20. The function should have the self-discipline to only read one parameter, since that's all the format string said there was. Reading more would lead to undefined behavior.

If what I've described is not the way your function works, then there's not much you can do on the calling end to solve it. But if it is how your function works, then there's nothing to do on the calling end, because there's no problem.

Another option, since you indicate that your "legacy code fails on null values," is to fix your legacy code so it doesn't fail anymore.

A third option is to simply write all four possibilities:

 if (a != null) {
   if (b != null)
     return myFunc(name, a, b);
   else
     return myFunc(name, a);
 } else {
   if (b != null)
     return myFunc(names, b);
   else
     return myFunc(names);
 }

More than two optional parameters, though, and the code starts getting unwieldy.

一念一轮回 2024-07-18 23:49:13

尝试将 System.List ToArray() 转换为 __arglist

myFunc(name, __arglist(args.ToArray()));

Try converting your System.List ToArray() before wrapping it in __arglist

myFunc(name, __arglist(args.ToArray()));

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文