C# 向 C++dll传递数组的问题

eakey 2019-04-18 11:54:12
有没有懂c#和c++的高手,问下,我在c#和c++间传递一个数组:
C++写的dll导出的函数
extern "C" __declspec(dllexport) int __stdcall SetBuf(int *Buffer, int Len);
{
Buffer[0] = 123;
}

C#的界面调用C++写的dll:
[System.Runtime.InteropServices.DllImport(@"Proc.dll",
EntryPoint = "SetBuf",
CharSet = System.Runtime.InteropServices.CharSet.Ansi,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
private static extern int SetPP(int[] Buffer, int Len);

如上,在C++的dll上改变Buffer[0] 的值,C#中Buffer[0]的值也跟着改变,这说明dll直接访问了C#的内存,而不是复制一个数组到dll,这会不会造成隐患?比如dll还在读数组呢,C#垃圾回收调整了数组的位置甚至回收了整个数组?
...全文
497 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
xian_wwq 2019-04-23
  • 打赏
  • 举报
回复
extern "C" __declspec(dllexport) int __stdcall GetPP1(BYTE *&Ptr1Byte, int &Len);
{
PtrByte = new BYTE[10000];
}

凡是c/c++中申请的内存
肯定需要在c/c++手动释放,
否则可能导致内存泄露
eakey 2019-04-20
  • 打赏
  • 举报
回复
引用 1 楼 xian_wwq 的回复:
“在C++的dll上改变Buffer[0] 的值,C#中Buffer[0]的值也跟着改变“ 要是不变,才是问题,那不是相等于函数的处理无效 c/c++ api基本上都遵循,谁调用,谁申请、释放资源的原则 int __stdcall SetBuf(int *Buffer, int Len) 指针就是地址,相当于定义ref类型的变量 就是要c#申请buffer,然后传给函数处理。 如果传入的是空或者长度不够,那就有空指针或操作越界的bug 如果c/c++ api传入参数的内容不让修改,那么 定义中对函数参数会增加const
你在上面说的c/c++ api基本上都遵循,谁调用,谁申请、释放资源的原则,比如我要从C++返回一数组,但在返回前我不知道数据的长度,所以我只能从C# ref IntPtr一个指针给C++,在C++中new出一个数组,此时调用用方是C#,这时是由C#释放这个数组吗?详细看下面代码: 我在c#和c++间传递一个数组: C++写的dll导出的函数 extern "C" __declspec(dllexport) int __stdcall GetPP1(BYTE *&Ptr1Byte, int &Len); { PtrByte = new BYTE[10000]; } C#的界面调用C++写的dll: [System.Runtime.InteropServices.DllImport(@"Proc.dll", EntryPoint = "GetPP1", CharSet = System.Runtime.InteropServices.CharSet.Ansi, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] private static extern int GetPP2(ref IntPtr PtrByte ref int Len); C#方法GetPP2在调用前会先把ref进去的PtrByte 置为IntPtr.Zero,然后调用后 byte[] ArrByte = new byte[Len]; Marshal.CopyPtrByte ArrByte, 0, Len); 在程序中测试现在可以正常从c++返回一个数组。 我现在的疑虑是,我应该再在C++中写一个函数暴露出C#接口释放(如下方的C++代码)这个在C++中申请的数组,还是用Marshal.FreeCoTaskMem/FreeHGlobal在C#中释放这个数组? 又或者说在C++和C#都不需要释放这个指针(IntPtr)?因为有人说IntPtr是自管理内存的,如果在在C++中delete了这个指针,IntPtr的自动管理又来释放一遍不是得出问题? extern "C" __declspec(dllexport) int __stdcall MthPtrByteFree(BYTE *PtrByte) { if (PtrByte) { delete[] PtrByte; PtrByte = nullptr; } return 0; }
eakey 2019-04-20
  • 打赏
  • 举报
回复
引用 楼主 eakey 的回复:
有没有懂c#和c++的高手,问下,我在c#和c++间传递一个数组: C++写的dll导出的函数 extern "C" __declspec(dllexport) int __stdcall SetBuf(int *Buffer, int Len); { Buffer[0] = 123; } C#的界面调用C++写的dll: [System.Runtime.InteropServices.DllImport(@"Proc.dll", EntryPoint = "SetBuf", CharSet = System.Runtime.InteropServices.CharSet.Ansi, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] private static extern int SetPP(int[] Buffer, int Len); 如上,在C++的dll上改变Buffer[0] 的值,C#中Buffer[0]的值也跟着改变,这说明dll直接访问了C#的内存,而不是复制一个数组到dll,这会不会造成隐患?比如dll还在读数组呢,C#垃圾回收调整了数组的位置甚至回收了整个数组?
谢谢
xian_wwq 2019-04-18
  • 打赏
  • 举报
回复
“在C++的dll上改变Buffer[0] 的值,C#中Buffer[0]的值也跟着改变“
要是不变,才是问题,那不是相等于函数的处理无效
c/c++ api基本上都遵循,谁调用,谁申请、释放资源的原则

int __stdcall SetBuf(int *Buffer, int Len)
指针就是地址,相当于定义ref类型的变量
就是要c#申请buffer,然后传给函数处理。
如果传入的是空或者长度不够,那就有空指针或操作越界的bug

如果c/c++ api传入参数的内容不让修改,那么
定义中对函数参数会增加const

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧