c# - How do I pass variable arguments from managed to unmanaged with a C++/CLI Wrapper? -


to implement params(variable arguments) functionality in managed domain, following in c++/cli such as:

funcmanaged(int n, ...array<int>^ variableparams) 

i'm dumbfounded on how pass unmanaged domain takes in variable arguments.

funcunmanaged(int n, ...) 

i tried pass array in, ended badly (access violations, junk data, etc).

//where unmanagedvariableparamsarray int array funcunmanaged(int n, unmanagedvariableparamsarray); 

resources suggest create va_list , pass around,

vfuncunmanaged(int n, va_list vl) 

but how create va_list in c++/cli domain take in variableparams? refactoring legacy unmanaged codebase not desirable solution.

if really, desperate not impossible. variadic function can called c code , call has generated c compiler. let's take example:

#include <stdarg.h> #include <stdio.h>  #pragma unmanaged  void variadic(int n, ...) {     va_list marker;     va_start(marker, n);     while (n--) {         printf("%d\n", va_arg(marker, int));     } } 

the compiler turn sample call variadic(3, 1, 2, 3); into:

00d31045  push        3   00d31047  push        2   00d31049  push        1   00d3104b  push        3   00d3104d  call        variadic (0d31000h)   00d31052  add         esp,10h   

note how arguments passed on stack, left right. stack gets cleaned after call. can emulate exact same call pattern using inline assembly. looks this:

void variadicadapter(int n, int* args) {     // store stack pointer can restore     int espsave;     _asm mov espsave,esp;     // push arguments     (int ix = n-1; ix >= 0; --ix) {         int value = args[ix];         _asm push value;     }     // make call     variadic(n);     // fix stack pointer     _asm mov esp,espsave; } 

pretty straight forward, shenanigans stack pointer restored. have adapter function can call managed code. you'll need pin_ptr<> turn array native pointer:

#pragma managed  using namespace system;  int main(array<system::string ^> ^args) {     array<int>^ arr = gcnew array<int>(3) { 1, 2, 3};     pin_ptr<int> arrp(&arr[0]);     variadicadapter(arr->length, arrp);     return 0; } 

works , not dangerous, tested in optimized release build. beware have no hope of making work if 64-bit code required.


Comments

Popular posts from this blog

javascript - DIV "hiding" when changing dropdown value -

Does Firefox offer AppleScript support to get URL of windows? -

android - How to install packaged app on Firefox for mobile? -