简体   繁体   English

如何使用C ++ / CLI包装器将变量参数从托管传递到非托管?

[英]How do I pass variable arguments from managed to unmanaged with a C++/CLI Wrapper?

To implement a params(variable arguments) functionality in the managed domain, we do the following in c++/cli such as: 为了在托管域中实现params(可变参数)功能,我们在c ++ / cli中执行以下操作:

funcManaged(int n, ...array<int>^ variableParams)

I'm dumbfounded on how to pass this to the unmanaged domain that takes in variable arguments. 我对如何将其传递给采用可变参数的非托管域感到困惑。

funcUnmanaged(int n, ...)

I tried to pass the array in, but it ended up badly (access violations, junk data, etc). 我试图传递该数组,但结果很糟糕(访问冲突,垃圾数据等)。

//where unmanagedVariableParamsArray is an int array
funcUnmanaged(int n, unmanagedVariableParamsArray);

Resources suggest to create a va_list and pass that around, 参考资料建议创建一个va_list并将其传递给周围,

vFuncUnmanaged(int n, va_list vl)

But how do I create the va_list in the c++/cli domain to take in the variableParams ? 但是,如何在c ++ / cli域中创建va_list来接受variableParams呢? Refactoring the legacy unmanaged codebase is not a desirable solution. 重构遗留的非托管代码库不是理想的解决方案。

If you are really, really desperate then this is not impossible. 如果您真的非常绝望,那么这并非没有可能。 A variadic function can only be called by C code and the call has to be generated by the C compiler. 可变参数函数只能由C代码调用,并且该调用必须由C编译器生成。 Let's take an 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 will turn a sample call like variadic(3, 1, 2, 3); 编译器将像variadic(3, 1, 2, 3);一样进行示例调用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 the arguments are passed on the stack, from left to right. 注意如何从左到右在堆栈上传递参数。 The stack gets cleaned up after the call. 调用后将清除堆栈。 You can emulate that exact same call pattern by using inline assembly. 您可以使用内联汇编来模拟完全相同的调用模式。 That looks like this: 看起来像这样:

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

Pretty straight forward, just some shenanigans to get the stack pointer restored. 很简单,只有一些技巧可以恢复堆栈指针。 Now you have an adapter function that you can call from managed code. 现在,您有了可以从托管代码中调用的适配器功能。 You'll need a pin_ptr<> to turn the array into a native pointer: 您需要一个pin_ptr <>才能将数组转换为本地指针:

#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 well and not actually that dangerous, tested in the optimized Release build. 运行良好,实际上没有那么危险,已在优化的Release版本中进行了测试。 Beware that you have no hope of making this work if 64-bit code is required. 请注意,如果需要64位代码,则您不希望这样做。

The general recommendation is that it is not recommended: See this article 一般建议是不建议这样做: 请参阅本文

I would suggest using a std::vector<int> to store the arguments. 我建议使用std::vector<int>来存储参数。

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

相关问题 C ++ / CLI:防止非托管资源的托管包装上的垃圾回收 - C++/CLI: preventing garbage collection on managed wrapper of unmanaged resource 从非托管库调用托管库时的C ++ / CLI包装器memleak - C++/CLI wrapper memleak when calling managed lib from unmanaged 使用托管c ++包装器将字符串从c#传递到非托管c# - pass string from c# to unmanaged c# using managed c++ wrapper 如何将结构从C#托管结构传递到C ++非托管DLL并得到结果结构? - How can I pass struct from C# managed to C++ unmanaged DLL and get struct in result? 从非托管C ++代码调用托管C#组件,我该如何定义配置 - calling managed c# component from unmanaged c++ code, how do i define config 如何为非托管C DLL创建C ++ \\ CLI包装器 - how to create a c++\cli wrapper for unmanaged c dll 如何将变量参数va_list从托管C ++传递到C#? - How to pass variable arguments va_list from managed C++ to C#? 从C#调用非托管C ++库(dll):如何在托管代码和非托管代码之间正确传递数据 - Calling unmanaged C++ library (dll) from C# : How to properly pass data between managed and unmanaged code 通过托管C ++包装程序从非托管C ++ dll运行C#函数 - Run a C# function from an unmanaged C++ dll through a managed C++ Wrapper 如何将结构从非托管C ++程序传递到C#程序? - How do I pass a struct from an unmanaged C++ program to a C# program?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM