将托管的 c# out 变量连接到非托管的本机 C++

Interfacing managed c# out variable to unmanaged, native C++

背景

大家好。我没有大量的 C++ 经验,但我有很多其他语言的经验。

我想要完成的是为要在本机 C++ 应用程序中使用的 C# 库创建包装器。到目前为止,我拥有的是一个 C++/CLI 包装器,它公开了 C# 库中的许多函数,以便我可以在我的本机 C++ 应用程序中使用它们。我这样做的方式就像这里展示的那样:

http://pragmateek.com/using-c-from-native-c-with-the-help-of-ccli-v2/

问题

我在将托管 C++/CLI 指针传递给 C# 库时遇到问题。 C# 库中的函数如下所示:

public bool SomeFunction(out byte[] buffer)

出于某种原因,我很难在我的 C++/CLI 包装器中传递指向此变量的指针。该函数正在请求托管引用,但 & 不适用于托管引用,而且我似乎也无法通过使用 % 使其正常工作。

我需要从函数中获取字节数组,我非常确定我可以将数据编组为我的 C++ 代码可以处理的类型。有什么建议吗?

编辑:删除了对 C++/CLI 代码的不明确引用。作为对 Hans 的回应,我成功地引用了 C# 库,因为我已经能够将数据从 C# 库来回传递到本机 C++ 代码。此外,我并不打算让这听起来如此神秘。 C# 库适用于我试图与 Micromanager 接口的显微镜相机。我正在处理的特定功能与从图像缓冲区中获取数据有关。

更新

感谢 Lucas,我​​找到了解决方案。无论出于何种原因,我认为我需要在我的 C++/CLI 库中传递一个指向 C# 库的指针。我的 C++/CLI 包装器的最终代码是:

public: bool SomeFunction(unsigned char* cBuffer, int* count) {
    cli::array<unsigned char>^ buffer;
    bool isFull = _referenceToManagedCSharpClass->SomeFunction(buffer);
    pin_ptr<unsigned char> pinnedArray = &buffer[0];
    cBuffer = pinnedArray;
    *count = buffer->Length;
    return isFull;
}

仍然不清楚为什么我不需要将指针传递给 C# 库,或者为什么我需要使用 pin_ptr 将指针存储在 cBuffer 中,但我想我会想出这个出去读书。感谢所有帮助过我的人。

假设您有以下 class:

ref class SomeClass
{
public:
    static bool SomeFunction([System::Runtime::InteropServices::OutAttribute] array<unsigned char>^% buffer)
    {
        buffer = gcnew array<unsigned char> { 'H', 'E', 'L', 'L', 'O' };
        return true;
    }
};

它可以用 C# 实现,只要您可以从 C++/CLI 访问它(添加引用 ),这并不重要。

要获取输出值,只需执行以下操作:

array<unsigned char>^ clrArray;
SomeClass::SomeFunction(clrArray);

clrArray 将设置为 SomeFunctionout 参数返回的值。

如果要从本机 C++ 访问原始字节,则需要 pin 数组。只要它被固定,您就可以安全地引用缓冲区。这是一个例子:

假设您有以下原生函数:

void NativeFunc(unsigned char *data, size_t count)
{
    std::copy(data, data + count, std::ostream_iterator<unsigned char>(std::cout, ""));
    std::cout << std::endl;
}

您可以拨打:

pin_ptr<unsigned char> pinnedArray = &clrArray[0];
NativeFunc(pinnedArray, clrArray->Length);

pinnedArray超出范围后,您必须将数据指针视为无效。它可能随时被 GC 重新定位。如果您需要固定更长的时间,请使用固定 GCHandle,但这更重量级。