包装原生 C++ .dll 中具有多个输出的函数,以便在 C# 中使用

发布于 2024-11-19 21:46:05 字数 735 浏览 4 评论 0原文

我将一些本机 C++ 代码包装在 C++/CLI .dll 中,以便在 .NET 项目中使用 - 主要是 C#。通话数量会很大,因此我希望以有效的方式做到这一点。我包装的函数采用以下参数:

int SomeFun(
       const char* input_text,
       int* output_array,
       bool* output_value);

由于 答案。我的问题是:

  1. 该函数需要指向 output_arrayoutput_value 的指针,这些指针需要在包装器内创建/清理并返回到托管组件。我该怎么做?
  2. 如何通过使用结构体作为返回值,从包装器 .dll 将多个值返回到托管环境?
  3. 现在,我正在尝试在包装器 .dll 内执行所有指针处理和托管/非托管交互,但是 本文(解决方案 3)建议在 C# 内部使用“不安全”环境是最快的。对于我想做的事情来说,这可能是更好的选择吗?我想这会使包装器不那么复杂,但也需要在 C# 中进行更精细的处理。

谢谢,

/大卫

I am wrapping some native C++ code in a C++/CLI .dll for use in .NET projects - mainly C#. The number of calls will be large so I am looking to do this in an effective way. The function I am wrapping takes the following arguments:

int SomeFun(
       const char* input_text,
       int* output_array,
       bool* output_value);

I know how to do an efficient System::String to const char* cast thanks to this answer. My questions are these:

  1. The function expects pointers to output_array and output_value which need to be created/cleaned-up and returned to the managed component all inside the wrapper. How do I do that?
  2. How do I return multiple values to the managed environment from the wrapper .dll - by using a struct as a return value?
  3. For now I am trying to do all the pointer handling and managed/unmanaged interaction inside the wrapper .dll but this article (Solution 3) suggests that using an "unsafe" environment inside C# is the fastest. Is this likely to be a better option for what I am trying to do? I guess it would make the wrapper less complex but also require more elaborate treatment in C#.

Thanks,

/David

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紅太極 2024-11-26 21:46:05

您可以像固定字符串一样固定数组,例如对于 byte[]:

pin_ptr<Byte> ptrBytes = &myArray[myArray->GetLowerBound(0)];

ptrBytes 现在可以用作 unsigned char*

您也可以固定来自 C# 的单个变量,例如使用作为引用的参数int 称为 int% ival:

pin_ptr<int> pInt =   &ival;

pInt 现在可以用作 int*

您可以使用 gcnew 创建数组,例如创建一个字节数组以返回到 C#:

array<Byte>^ streambuf = gcnew array<Byte>(bufSize+16);

您现在可以用以下内容填充它Streambuf[index],在循环中重新打包 C++ 数组,或者您可以固定它并在将其返回到 C# 之前执行 memcpy。

我通常不返回结构。我通常在 C++/CLI 函数包装器中定义每个参数。例如,如果一个结构有两个 int 和一个字符串,我将使用 ref 关键字(C++/CLI 中的 %,例如 int% ival)为每个参数创建一个参数。如果必须返回大量值,最简单的方法是返回使用 gcnew 创建的类,而不是结构体。

如果您想加快数组访问速度并且您的 C# 代码很简单,那么使用不安全代码是一种可行的方法。如果您已经有 C++ 代码,并且它使用 STL 并且非常复杂,并且您不想重写它,特别是如果您有大量指针算术和强制转换,请坚持使用 C++/CLI 包装器。

You can pin arrays the same way you pin strings, e.g. for byte[]:

pin_ptr<Byte> ptrBytes = &myArray[myArray->GetLowerBound(0)];

ptrBytes can now be used as an unsigned char*

You can pin single variables that come from C#, too, for example with a parameter that is a ref to an int called int% ival:

pin_ptr<int> pInt =   &ival;

pInt can now be used as an int*

You can create arrays with gcnew, for example to create an array of Bytes to return to C#:

array<Byte>^ streambuf = gcnew array<Byte>(bufSize+16);

You can now fill this with streambuf[index], repacking a C++ array in a loop, or you could pin it and do a memcpy before returning it to C#.

I do not usually return structs. I usually define each parameter in the C++/CLI function wrapper. For example if a struct had two ints and a string, I'd make each a parameter with ref keyword (% in C++/CLI, e.g. int% ival). if you must return a large number of values it's easiest to return a class you create with gcnew, not a struct.

Using unsafe code is the way to go if you are trying to speed up array access and your C# code will be straightforward. If you already have C++ code and it uses the STL and is very complex and you don't want to rewrite it, especially if you have lots of pointer arithmetic and casts, stick with a C++/CLI wrapper.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文