我无法使下面的 p/invoke 代码正常工作,请帮忙,谢谢。
下面的顶点在 C++ 调用后保持为空。我尝试使用 IntPtr 而不是 string[],C++ 调用后 IntPtr 保持为 0。
C++代码
extern "C" __declspec(dllexport)
float compute_similarity(char** vertices)
{
vertices = new char*[2];
vertices[0] = new char[3];
vertices[1] = new char[3];
strcpy(vertices[0], "he");
strcpy(vertices[1], "ha");
return 1.01;
}
C#代码
[DllImport("demo.dll", EntryPoint = "compute_similarity",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern float compute_similarity(out string[] vertices);
//also tried 'static extern float compute_similarity(out IntPtr vertices);'
public string Func()
{
string[] vertices; //also tried 'IntPtr vertices'
float sim = compute_similarity(out vertices);
//break point here vertices stays null(or 0 for IntPtr)
return sim.ToString();
}
最佳答案
我不认为它可以通过这种方式正确完成,因为您无法指定 P/Invoke 在将其转换为托管字符串后必须使用 delete[]
调用释放内存。
但是,使用 BSTR
的 SAFEARRAY
和 MarshalAs
属性,您可能有战斗的机会。
extern "C" __declspec(dllexport)
float compute_similarity(SAFEARRAY** vertices)
{
SAFEARRAY *pArr = SafeArrayCreateVector(VT_BSTR, 0, 2);
if(pArr != NULL)
{
LONG index = 0;
BSTR bs = SysAllocString(L"he");
SafeArrayPutElement(pArr, &index, bs);
SysFreeString(bs);
index = 1;
bs = SysAllocString(L"ha");
SafeArrayPutElement(pArr, &index, bs);
SysFreeString(bs);
}
*vertices = pArr;
return 1.01;
}
[DllImport("demo.dll", EntryPoint = "compute_similarity", CallingConvention = CallingConvention.Cdecl)]
static extern float compute_similarity(
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)] out string[] vertices
);
您仍然可以使用 IntPtr
(并在 C# 端手动进行编码(marshal)处理,同时导出 delete_strings
函数),但请记住,您的函数必须采用其 char**
引用,否则不能实际修改它。
关于c# - pinvoke - 传递一个字符串 [] 作为输出参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19273828/