c# - 如何从 C# 中的 C++ dll 获取数组的内容
问题描述
我想在 C++ 中使用 DLL 中的函数和 C#。
我将字符串数据存储在向量中。
我的 C++ 文件包含:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern "C" __declspec(dllexport) std::vector<std::string> GetProduct();
std::vector<std::string> GetProduct()
{
std::vector<std::string> vectProduct;
vectProduct.push_back("Citroen");
vectProduct.push_back("C5");
vectProduct.push_back("MOP-C5");
return vectProduct;
}
在 C# 中
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices;
namespace ConsoleApplication
{
class Program
{
[DllImport("ProductLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern StringBuilder GetProduct();
static void Main(string[] args)
{
StringBuilder vectProduct_impl = GetProduct();
}
}
}
我不知道如何继续浏览c#中的数组。我不知道使用矢量是否最佳。如果您有其他解决方案,我准备好了。
请帮忙。
解决方案
我最喜欢的传递字符串数组 C++-->C# 的方法是使用委托。
C#:
// If possible use UnmanagedType.LPUTF8Str
// or under Windows rewrite everything to use
// wchar_t, std::wstring and UnmanagedType.LPWStr
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void AddAnsi([MarshalAs(UnmanagedType.LPStr)] string str);
[DllImport("CPlusPlusSide.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void TestReturnArrayStrings(AddAnsi add);
进而
var lst = new List<string>();
TestReturnArrayStrings(lst.Add);
foreach (string str in lst)
{
Console.WriteLine(str);
}
和 C++:
#include <string>
#include <vector>
extern "C"
{
__declspec(dllexport) void TestReturnArrayStrings(void (add)(const char* pstr))
{
std::string str1 = "Hello";
std::string str2 = "World";
add(str1.data());
add(str2.data());
// Example with std::vector
add("--separator--"); // You can even use C strings
std::vector<std::string> v = { "Foo", "Bar" };
// for (std::vector<std::string>::iterator it = v.begin(); it != v.end(); ++it)
for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it)
{
add(it->data());
}
add("--separator--"); // You can even use C strings
// With C++ 11
// for (auto& it: v)
for (const auto& it: v)
{
add(it.data());
}
}
}
这里的“技巧”是 C# 将委托传递给 C++List<string>.Add()
方法,而 C++ 直接“填充” C# List<>
。C++管理的内存留在C++端,C#管理的内存留在C#端。没有跨内存所有权的问题。正如您可以想象的那样,将“技巧”扩展到任何其他.Add()
方法(例如HashSet<string>
或Dictionary<string, string>
.
作为旁注,我创建了一个github,其中包含许多关于 C/C++ 和 C#(.NET Framework 和 .NET Core/5.0)之间编组的示例。
推荐阅读
- security - 防止跨站脚本,但仍支持 HTML 文件上传
- python - 温度传感器减慢了我的 GUI python 程序(Python3,树莓派)
- reactjs - 重构样式化的组件
- javascript - 使用 Bootstrap 的图像上传警报
- swift - 在字母处将字符串转换/拆分为数组
- python - 如何并行和在线运行函数?
- python - django: app 崩溃 heroku[router]: at=error code=H10 desc="App crashed"
- c# - 为 EF 6.x 和 EF Core 重用 EF 实体
- python - 如何停止实际的迭代并跳到下一个 Python
- java - @AutoValue 类中是否需要不可变集合?