简体   繁体   English

C#使用CPP中未知数量的args调用CPP函数

[英]C# invoking CPP function with unknown number of args from CPP

i have a function in CPP with the following prototype: 我在CPP中有一个函数,具有以下原型:

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

i import it from a C# using DLLImport attribute. 我使用DLLImport属性从C#导入它。 the questions are: how do i define the prototype in the C# (under the DLLImport attribute)? 问题是:我如何在C#中定义原型(在DLLImport属性下)? how do i pass the arguments to this function? 我如何将参数传递给这个函数? thanks 谢谢

This is called variadic function. 这称为可变函数。 The information on P/Invoke support for them is rather scarce, here's what I found out. P / Invoke对它们的支持信息相当稀缺,这就是我发现的。

I couldn't find a way to directly DllImport a function with variable number of arguments. 我找不到直接DllImport一个具有可变数量参数的函数的方法。 I had to DllImport all variations of arguments as different overloads. 我不得不将所有参数变量DllImport作为不同的重载。

Let's take for example wsprintf . 我们以wsprintf为例 It has the following prototype in winuser.h : 它在winuser.h有以下原型:

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

It can be used from C# like this: 它可以在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);
  }
}

Now to address your complexFunction . 现在来解决你的complexFunction

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

Its varargs list should be addressed in the same way: by providing all useful overloads. 它的varargs列表应该以相同的方式解决:提供所有有用的重载。 But there is also another complication - return type. 但是还有另一种并发症 - 返回类型。 I assume that complexFunction allocates and returns array of char . 我假设complexFunction分配并返回char数组。 In this case it's most likely that the caller is responsible for array's deallocation. 在这种情况下,调用者最有可能负责数组的释放。 To allow for this you should import deallocation routine as well, let's call it void free(void*) . 为了实现这一点,您还应该导入释放例程,让我们将其称为void free(void*)

Assuming all that's been assumed, C# code using complexFunction would look like this: 假设已经假定所有这些,使用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);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM