2

在我的应用程序中,我有 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,则它不会包含在参数列表中(我的旧代码在 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]);

有人知道吗?

4

2 回答 2

2

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);
 }

但是,超过两个可选参数,代码开始变得笨拙。

于 2009-01-14T16:31:47.180 回答
0

尝试在将 System.List ToArray() 包装到 __arglist 之前转换它

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

于 2011-03-12T20:12:52.177 回答