如何在 C# 中封送集合以传递给本机 (C++) 代码
我正在从事企业应用程序开发。整个应用程序都是用 C++ 开发的,除了 UI 是用 C# 开发的,现在是时候将 UI 与 C++ 代码挂钩了。经过详细研究,我选择了 PInvoke 来做到这一点。 一切都很成功,我唯一遇到的问题是如何将集合传递给 C++ 代码。 例如:
C# 侧代码
List<string> lst = new List<string>();
lst.Add("1");
lst.Add("2");
lst.Add("3");
lst.Add("4");
C++ 侧代码
std::vector<std::string> vStr;
现在我如何将 lst 传递给本机 C++ 代码
I am working on an enterprise application development. the entire application is developed in c++, except the UI, which is developed in c#, now its time to hookup the UI with c++ code. After detailed study i choose PInvoke in order to do so.
All is successful, the only case where i stuck is that how can i pass collection to C++ code.
e.g:
C# Side Code
List<string> lst = new List<string>();
lst.Add("1");
lst.Add("2");
lst.Add("3");
lst.Add("4");
C++ Side Code
std::vector<std::string> vStr;
Now how do i pass lst to native C++ code
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如 mzabsky 提到的,您无法封送这些类型。但是,您可以编组数组:
理论上的 C++ 导出:
P/Invoke 签名:
来自 C# 的调用:
请注意,我在这里使用 std::wstring;您可以使用 char 代替 wchar_t,使用 LPStr 代替 LPWStr,使用 std::string 代替 std::wstring。
请注意,这将从列表中分配一个数组,然后向量将复制该数组的内容。如果原始列表的大小很小,那么这个问题应该可以忽略不计。
编辑:修复标记(< 和 >)。
As mzabsky mentioned, you cannot marshal these types. You can, however, marshal an array:
The theoretical C++ export:
The P/Invoke signature:
The call from C#:
Note that I'm using std::wstring here; you could instead use char instead of wchar_t, LPStr instead of LPWStr, and std::string instead of std::wstring.
Note that this will allocate an array from the list and then the vector will copy the array's contents. If the original list is small in size, this should be of negligible concern.
Edit: fixing markup (< and >).
你不能这样做,只能编组 C 类型。您必须编写一个 C++/CLI 包装器(或围绕 C++ 向量的 C 包装器)。
查看此答案。
You can't do this, only C types can be marshalled. You will have to write a C++/CLI wrapper (or a C wrapper around the C++ vector).
See this answer.
是的。你可以。实际上,不仅仅是
std::string
、std::wstring
,任何标准 C++ 类或您自己的类都可以从 C#/.NET 进行编组或实例化和调用。在 C# 中包装
std::vector
确实可以仅使用常规 P/Invoke Interop,但它很复杂。甚至任何类型的std::map
都可以在 C#/.NET 中完成。从 .NET 世界实例化 C++ 对象的基本思想是从 .NET 分配 C++ 对象的精确大小,然后调用从 C++ DLL 导出的构造函数来初始化该对象,然后您将能够调用任何访问该 C++ 对象的函数,如果任何方法涉及其他 C++ 类,您还需要将它们包装在 C# 类中,对于具有原始类型的方法,您可以简单地 P/Invoke 它们。如果你只有几个方法需要调用,那会很简单,手动编码不会花很长时间。当您使用完 C++ 对象后,您将调用 C++ 对象的析构函数方法,该方法也是导出函数。如果没有,那么您只需从 .NET 中释放内存即可。
这是一个例子。
有关详细信息,请参阅以下链接,
C#/.NET PInvoke Interop SDK
(我是SDK工具的作者)
Yes. You can. Actually, not just
std::string
,std::wstring
, any standard C++ class or your own classes can be marshaled or instantiated and called from C#/.NET.Wrapping a
std::vector<any_type>
in C# is indeed possible with just regular P/Invoke Interop, it is complicated though. even astd::map
of any type can be done in C#/.NET.The basic idea of instantiating a C++ object from .NET world is to allocate exact size of the C++ object from .NET, then call the constructor which is exported from the C++ DLL to initialize the object, then you will be able to call any of the functions to access that C++ object, if any of the method involves other C++ classes, you will need to wrap them in a C# class as well, for methods with primitive types, you can simply P/Invoke them. If you have only a few methods to call, it would be simple, manual coding won't take long. When you are done with the C++ object, you call the destructor method of the C++ object, which is a export function as well. if it does not have one, then you just need to free your memory from .NET.
Here is an example.
For the detail, please see the below link,
C#/.NET PInvoke Interop SDK
(I am the author of the SDK tool)