将托管的 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
将设置为 SomeFunction
从 out
参数返回的值。
如果要从本机 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
,但这更重量级。
背景
大家好。我没有大量的 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
将设置为 SomeFunction
从 out
参数返回的值。
如果要从本机 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
,但这更重量级。