N/Direct - The .NET Interoperability Resource Center 

FAQ

 

 

 

Most Valuable Professional

How do I call a C/C++ vararg function from .NET?
Written: 6/27/2002 Updated: 6/27/2002

You should write overloads for each set of parameter types you intend to call the function with. Also, make sure the methods are declared with CallingConvention.Cdecl. For example, calling printf from the VC++ runtime library in three different ways is done like this.

C#
[DllImport("msvcrt40.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
static extern int printf(string format, int p1);
[DllImport("msvcrt40.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
static extern int printf(string format, int p1, double p2);
[DllImport("msvcrt40.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
static extern int printf(string format, int p1, string p2);
static void Main()
{
  printf( "%d\r\n", 123 );
  printf( "%d, %f\r\n", 123, 456.78 );
  printf( "%d, %s\r\n", 123, "abc" );
}
    

VB.NET
<DllImport("msvcrt40.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
Shared Function printf(ByVal format As String, ByVal p1 As Integer) As Integer
End Function
<DllImport("msvcrt40.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
Shared Function printf(ByVal format As String, ByVal p1 As Integer, ByVal p2 As Double) As Integer
End Function
<DllImport("msvcrt40.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
Shared Function printf(ByVal format As String, ByVal p1 As Integer, ByVal p2 As String) As Integer
End Function
Shared Sub Main()
  printf("%d" & Environment.NewLine, 123)
  printf("%d, %f" & Environment.NewLine, 123, 456.78)
  printf("%d, %s" & Environment.NewLine, 123, "abc")
End Sub
    

In VC#.NET, if you're willing to rely on undocumented features, you can also use the __arglist keyword to define a real .NET vararg method. That way, you can use a single method for all kinds of parameters. __arglist is used both in the method declaration and at the call site to enclose the parameters to pass in.

C#
[DllImport("msvcrt40.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
static extern int printf(string format, __arglist);
static void Main()
{
  printf( "%d\r\n", __arglist(123) );
  printf( "%d, %f\r\n", __arglist(123, 456.78) );
  printf( "%d, %s\r\n", __arglist(123, "abc") );
}