【问题标题】:C# invoking CPP function with unknown number of args from CPPC# 使用来自 CPP 的未知数量的 args 调用 CPP 函数
【发布时间】:2008-10-18 11:56:04
【问题描述】:

我在 CPP 中有一个函数,原型如下:

char* complexFunction(char* arg1, ...);

我使用 DLLImport 属性从 C# 导入它。 问题是: 如何在 C# 中定义原型(在 DLLImport 属性下)? 我如何将参数传递给这个函数? 谢谢

【问题讨论】:

    标签: c# c++ interop pinvoke variadic-functions


    【解决方案1】:

    这称为可变参数函数。对它们的 P/Invoke 支持的信息相当少,这是我发现的。

    我找不到直接DllImport 具有可变数量参数的函数的方法。我不得不将DllImport 所有变体参数作为不同的重载。

    我们以wsprintf 为例。它在winuser.h 中有如下原型:

    int WINAPIV wsprintf(      
        LPTSTR lpOut,
        LPCTSTR lpFmt,
        ...);
    

    它可以像这样从 C# 中使用:

    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    
    class C {
    
      // first overload - varargs list is single int
      [DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)]
      static extern int wsprintf(
        [Out] StringBuilder buffer,
        string format,
        int arg);
    
      // second overload - varargs list is (int, string)
      [DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)]
      static extern int wsprintf(
        [Out] StringBuilder buffer,
        string format,
        int arg1,
        string arg2);
    
      public static void Main() {
        StringBuilder buffer = new StringBuilder();
        int result = wsprintf(buffer, "%d + %s", 42, "eggs!");
        Console.WriteLine("result: {0}\n{1}", result, buffer);
      }
    }
    

    现在联系您的complexFunction。

    char* complexFunction(char* arg1, ...);
    

    它的可变参数列表应该以同样的方式处理:通过提供所有有用的重载。但是还有另一个复杂的地方——返回类型。我假设complexFunction 分配并返回char 的数组。在这种情况下,调用者很可能负责数组的释放。为此,您还应该导入解除分配例程,我们称之为void free(void*)。

    假设所有这些,使用 complexFunction 的 C# 代码将如下所示:

    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    
    class C {
    
      [DllImport("your.dll",
                 CallingConvention=CallingConvention.Cdecl,
                 CharSet=CharSet.Ansi)]
      static extern IntPtr complexFunction(
        string format,
        int arg1, int arg2);
    
      [DllImport("your.dll", CallingConvention=CallingConvention.Cdecl)]
      static extern void free(IntPtr p);
    
      public static void Main() {
        IntPtr pResult = complexFunction("%d > %s", 2, 1);
        string sResult = Marshal.PtrToStringAnsi(pResult);
        free(pResult);
        Console.WriteLine("result: {0}", sResult);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-03-27
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      • 2023-03-27
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      • 2018-04-26
      相关资源
      最近更新 更多