从C+;从双指针结构封送字符*+;到C# 目标:从C++中检索结构数组,从C++侧完成,返回指针到Stutt指针(双指针)(不在我的控件中)。< /P> 样本C++代码: struct Output { char* Name; }; extern "C" { __declspec(dllexport) Output** getoutput() { Output* items = (Output*)malloc(sizeof(Output) * 4); items->Name = "Hello World"; return &items; } }
c#侧码:从C+;从双指针结构封送字符*+;到C# 目标:从C++中检索结构数组,从C++侧完成,返回指针到Stutt指针(双指针)(不在我的控件中)。< /P> 样本C++代码: struct Output { char* Name; }; extern "C" { __declspec(dllexport) Output** getoutput() { Output* items = (Output*)malloc(sizeof(Output) * 4); items->Name = "Hello World"; return &items; } },c#,c++,c,C#,C++,C,c#侧码: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct Output { [MarshalAsAttribute(UnmanagedType.LPStr)] public string Name; }; [DllImport(@"CPPInvokeExposed.dll", CallingConvention =
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Output
{
[MarshalAsAttribute(UnmanagedType.LPStr)]
public string Name;
};
[DllImport(@"CPPInvokeExposed.dll",
CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr getoutput();
static void Main(string[] args)
{
var output = Program.getoutput();
Output[] outputs = new Output[1];
MarshalUnmananagedArray2Struct<Output>(output, 1, out outputs);
**outputs[0]// this has junk chars**
}
public static void MarshalUnmananagedArray2Struct<T>(IntPtr unmanagedArray, int length, out T[] mangagedArray)
{
var size = Marshal.SizeOf(typeof(T));
mangagedArray = new T[length];
for (int i = 0; i < length; i++)
{
IntPtr ins = new IntPtr(unmanagedArray.ToInt64() + i * size);
mangagedArray[i] = Marshal.PtrToStructure<T>(ins);
}
}
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
公共结构输出
{
[MarshalAsAttribute(UnmanagedType.LPStr)]
公共字符串名称;
};
[DllImport(@“cppInvokeeExposed.dll”),
CallingConvention=CallingConvention.Cdecl)]
公共静态外部IntPtr getoutput();
静态void Main(字符串[]参数)
{
var output=Program.getoutput();
输出[]输出=新输出[1];
MarshallUnmaNageDarray2Struct(输出,1,输出);
**输出[0]//这有垃圾字符**
}
public static void marshallUnmanageDarray2struct(IntPtr unmanagedArray,int length,out T[]manageDarray)
{
var size=Marshal.SizeOf(typeof(T));
mangagedArray=新的T[长度];
for(int i=0;i
不清楚问题是C++还是C代码。正确的方法是从结构中存在的C++获得char *。p> <一个奇怪的事情是,对于同一代码,如果C++代码返回单个指针(输出*)而不是双指针(输出**),则没有垃圾字符,得到正确的赋值。当从C++返回双指针时,好像有什么不对。
< P> C++代码导致不明确行为:
return&items代码>
这将返回自动变量的地址。
当函数返回时,该变量将不再存在。访问该内存位置是非法的,会导致未定义的行为
一个干净的解决方案是返回指针本身,而不是地址。但在您的问题中,您声明返回类型不在您的控制之下
在这种情况下,您必须自己创建第二级间接寻址:
__declspec(dllexport) Output** getoutput()
{
Output* items = (Output*)malloc(sizeof(Output) * 4);
items->Name = "Hello World";
Output **retval = (Output**)malloc(sizeof(Output*))
*retval = items;
return retval;
}
当然,您还需要注意在以后释放两个级别的内存分配
顺便说一句:
为4个结构分配内存,但只为第一个元素的成员分配一个值。return&items代码>返回自动变量的地址。当函数返回时,该变量将不再存在。访问该内存位置是非法的,会导致未定义的行为。相反,返回项
就可以了。只需确保分配内存的方式在C#side(,)上有相应的deallocator即可。@GSerg pszReturn=(char*)::CoTaskMemAlloc(ulSize);即使如此,同样的(垃圾字符)问题仍然存在。@Gerhardh因为返回您提到的&items而得到编译器错误,但我没有找到任何方法来解决这个问题。解决这个问题的方法是返回items
,而不是&items
。更好的方法是将items
作为out参数传递,并与告诉大小的int*
参数一起传递,这样就可以在not之上进行自动编组。在生产中,我分配n个数字并填充所有数据,例如,我设置为first element。我尝试了一级间接寻址,但没有更改c#代码。垃圾问题依然存在。