3

Background:
I have written the following function in C++:

extern "C" __declspec(dllexport) int test(const char*, ...);

And I am using P/Invoke to call it from C#:

[DllImport("foo/bar.dll", EntryPoint = "test")]
public static unsafe extern int __unmanaged__test(byte* buffer, __arglist);


Problem:
I need to initialize the __arglist dynamically, meaning that I have an Array<object>, which I have to convert into the __arglist before calling the C++-function.

I have tried the following, but it returns an compiler error:

unsafe {
    byte[] buffer = ....
    object[] args = ....

    // ....

    fixed (byte* ptr = buffer)
        return __unmanaged__test(ptr, __arglist(args)); // <--ERROR
}

Does anyone know a way to solve this problem?


for those who do not know what __arlist is: http://bartdesmet.net/blogs/bart/archive/2006/09/28/4473.aspx
user2864740
  • 60,010
  • 15
  • 145
  • 220
unknown6656
  • 2,765
  • 2
  • 36
  • 52

2 Answers2

1

You need to use the C-style calling convention - the others (including the default Stdecl) don't support varargs:

[DllImport("foo/bar.dll", EntryPoint = "test", 
           CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int __unmanaged__test(byte* buffer, __arglist);

Another tricky part is that __arglist(...) is a compile-time feature - it simply generates a (virtual) stack push for each of its "arguments". This means that you can't use it with arguments not known at compile-time - in your sample code, you're simply attempting to make a single argument, typed object[].

Building the helper reflection methods isn't too hard - see Calling varargs method via DynamicMethod for an example. I cannot test this, but I'd guess Expression could be used to build this code easily - if you didn't have to pass that byte*, that is (do you really have to? passing byte[] could work just as well).

Community
  • 1
  • 1
Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Thank you, but the error still exists. I think its the conversion between the array and the __arglist – unknown6656 Aug 24 '15 at 06:52
  • 1
    @Unknown6656 Well, yeah, you can't do that. If you need to build `__arglist` dynamically (that is, you don't know the types and amount of arguments in advance), you'll probably have to use reflection. See http://stackoverflow.com/questions/29458616/calling-varargs-method-via-dynamicmethod for example. – Luaan Aug 24 '15 at 06:54
0

The comment Luuan wrote (see here) had the solution I needed:

quote:

If you need to build __arglist dynamically (that is, you don't know the types and amount of arguments in advance), you'll probably have to use reflection.
See stackoverflow.com/questions/29458616/… for example

Community
  • 1
  • 1
unknown6656
  • 2,765
  • 2
  • 36
  • 52