Mita
Mita

Reputation: 263

Calling a .NET function with variable number of parameters from unmanaged code

I would like to call C# function with variable number of parameters:

void f1(object arg1, params object[] argsRest);

from unmanaged, C function with variable parameters that wraps f1.

How can this be achived?

Upvotes: 1

Views: 654

Answers (4)

Mita
Mita

Reputation: 263

Thanks, I have achieved this.

In C function:

void UnmanagedClass::foo(int i, char *message, ...);

during excuting, variable 'i' and message will be put on stack, and then the address of additional parameters array.

I there is mixed unmanaged/managed code in one CLR project, function with variable number of parameters will be compiled as unmanaged function (here) . This is why i made a bridge class with member function:

void ManagedClass::foo(int i, char * message, unsigned int *params);

and implemented:

void UnmanagedClass::foo(int i, char *message, ...) {
    unsigned int *p = (unsigned int*) &message;
    p++;
    ManagedClass::foo(i, message, (unsigned int) p);
}

I didn't need number of parameters, since the 'message' was carrying info about the number and the type of parametes in a printf fashion way.

This way, in 'ManagedClass::foo()' function I parsed the array 'p', created instances of corresponding managed types, arranged them in objects array and passed them to a managed method with invariant number of arguments.

Upvotes: 0

mcdave
mcdave

Reputation: 2580

To expose your managed function you will need to write a mixed mode DLL that acts as a bridge (You should read this article on MSDN as background.)

Your c++-cli bridge DLL will contain code similar to the following ...

#include <cstdarg>

extern "C" {
    __declspec(dllexport) void f1wrapper(void *arg1, int nargs, ...)
    {
        array<Object^>^ managedArgs = gcnew array<Object^>(nargs);
        va_list args;
        va_start(args, nargs);
        for (int _i = 0; _i < nargs; ++_i)
        {
            managedArgs[_i] = ???; // <- you need to translate args
        }
        va_end(args);

        // Call your function
        Object^ managedArg1 = ???; // <- translate arg1
        f1(managedArg1, managedArgs);
    }
}

You then link against the mixed mode DLL and call f1wrapper(...) from your C code. Not complete, but should provide enough foundation for you to experiment.

Upvotes: 1

Vitaliy Liptchinsky
Vitaliy Liptchinsky

Reputation: 5299

params object[] is basically just an array, so treat it as array.

Upvotes: 0

Henrik
Henrik

Reputation: 9945

From C you need to pass the length of your array as a parameter to C# so that you can then marshal the pointer to the array into a c# array. I don't think you can directly use that function signature from C.

Upvotes: 1

Related Questions