我在C ++,_ GetFileList中有一个函数,我试图将一个字符串列表/数组返回给C#代码。我没有和wstring *
或任何其他类型结婚,这就是我找到的例子,但是我试图让它返回一个列表/数组而不仅仅是一个字符串。我如何编组这个在C#端有多个字符串?
C ++代码:
extern "C" __declspec(dllexport) wstring * __cdecl _GetFileList(int &size){
std::list<wstring> myList;
//Code that populates the list correctly
size = myList.size();
wstring * arr = new wstring[size];
for( int i=0;i<size;i++){
arr[i] = myList.front();
myList.pop_front();
}
return arr;
}
我从C#那里称之为:
[DllImport(@"LinuxDirectory.Interface.dll")]
private static extern IntPtr _GetFileList(ref int size);
public bool GetFileList() {
int size = 0;
IntPtr ptr = _GetFileList( ref size );
//WHAT DO I DO HERE TO GET THE LIST OF STRINGS INTO SOMETHING I CAN READ?
}
我尝试过使用Marshal.PtrToStringUni,Marshal.PtrToStringAnsi以及结构,但似乎无法正确使用语法。
答案 0 :(得分:2)
你不是。 P / Invoke只能处理与C兼容的函数签名,这意味着指针必须是普通的数据,而不是完整的C ++类。
如果您可以重写C ++代码,请将其更改为调用SysAllocString
并返回BSTR
,这是OS提供的字符串类型,用于在以不同语言编写的组件之间进行数据交换。 P / invoke已经具有接收BSTR
的所有正确魔力,只需在p / invoke声明中使用C#string
类型。
如果您无法更改C ++签名,则必须将其包装起来。要么使用C ++ / CLI,它可以处理C ++类和.NET,要么使用标准C ++并创建并返回BSTR
,从std::wstring
复制数据。
对于多个字符串,您可以使用OS提供的数组类型(SAFEARRAY),它能够在内部携带BSTR,并且再次与语言无关。或者,使用适当的(当前不会出现在数据中)分隔符来加入和拆分可能更容易。
这里有一些非常好的信息:https://msdn.microsoft.com/en-us/magazine/mt795188.aspx
运行.NET Framework(Microsoft实现,在Windows上),您可以使用帮助程序类:
#include <windows.h>
#include <atlbase.h>
#include <atlsafe.h>
#include <string>
extern "C" __declspec(dllexport) LPSAFEARRAY GetFileList()
{
std::vector<std::wstring> myList;
//Code that populates the list correctly
size = myList.size();
CComSafeArray<BSTR> sa(size);
int i=0;
for( auto& item : myList ) {
CComBSTR bstr(item.size(), &item[0]);
sa.SetAt(i++, bstr.Detach()); // transfer ownership to array
}
return sa.Detach(); // transfer ownership to caller
}
在C#端,p / invoke处理它:
[DllImport("NativeDll.dll"),
return:MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
public static extern string[] GetFileList();
您的问题表明您可能在Linux上。不幸的是,我发现的文档似乎说Mono的p / invoke根本不知道如何处理可变大小的数组。因此,您可以手动执行所有操作,包括解除分配(问题中的代码泄漏new wstring[size]
- C#绝对不知道如何调用C ++ delete[]
运算符。看看Mono.Unix.UnixMarshal.PtrToStringArray
。