将托管的c#out变量与非托管的本机c++接口

本文关键字:本机 c++ 接口 变量 c#out | 更新日期: 2023-09-27 18:20:40

背景

大家好。我没有大量的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中,但我想我会通过阅读来解决这个问题。感谢所有帮助我的人。

将托管的c#out变量与非托管的本机c++接口

假设您有以下类:

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访问它(正如Hans所说,添加一个引用)。

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

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,但这更重。