2015-11-05 114 views
-2

背景接口托管C#out变量非托管,本机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代码的不清楚引用。为了回应汉斯,我成功地引用了C#库,因为我已经能够将数据从C#库传递到本地C++代码。另外,我不打算让这听起来很神秘。 C#库适用于我试图与Micromanager连接的显微镜相机。我正在处理的特定功能与抓取图像缓冲区中的数据有关。

更新

感谢卢卡斯,我有一个解决方案。无论出于什么原因,我认为我需要将指针传递给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,但我想我会通过阅读来解决这个问题。感谢所有帮助过我的人。

+0

*你很不清楚为什么你发布了这个方法的C++/CLI声明。你不应该自己写它,因为它存在于C#库中。您的C++/CLI项目必须添加对C#库的引用。 –

+0

我很抱歉不清楚。正如我所说的,我对C++相对来说比较陌生。正如我上面所说,我必须编写一个接口来将C#库展示给本机C++(不是C++/CLI)。我发布了C++/CLI,因为这是我在SDK中给出的参考点,我认为这是在C++/CLI中公开此特定C#函数的起点(因为SDK C++/CLI已经是一个很好的开始指向我已经包含的其他功能)。 – FirstPrime

回答

1

假设你有下面的类:

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访问(添加引用as Hans said)。

要获得产值,你只需做到以下几点:

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

clrArray将被设置为从out参数由SomeFunction返回的值。

如果要从本地C++访问原始字节,则需要引脚该数组。只要固定它,就可以安全地引用缓冲区。这里有一个例子:假设你有以下的本地函数

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

+0

我尝试了第一个定义clrArray的建议,然后将它与C#库一起使用。我不需要编组(这是因为数组是cli :: array)以将其转换为C++吗?如果是这种情况,那么我试图用循环条目来编组数据的方法不起作用,因为在尝试使用clrArray.Count时出现错误。我将不得不明天尝试你最后的方法。我用pin_ptr尝试了一下它的变体,但我想我可能弄错了。谢谢您的帮助。 – FirstPrime

+0

你说得对,你不能直接在C++中使用'cli :: array' *。你有两个解决方案:你可以编组数组(这意味着你将它的内容复制到本地缓冲区),或者你可以像我在答案中那样获取一个指向数据的指针。这可以在没有拷贝开销的情况下工作,你只需要确保它保持固定。 –

+0

啊,好吧。那我误解了你的答案。好吧,看起来我使用的是Count而不是Length,当我尝试这样的事情时就开始了。我有一个剩余的问题是为什么我不需要传递指向C#函数的指针。再次,我对无知表示歉意。 – FirstPrime