C#中调用c++dll的结构体传递问题

tianxiaoying22 2015-08-19 01:56:46
c++中发的原型是这样的:
typedef struct ucvACF
{
float *ucvTemp;
float *ucvGx;
float *ucvGy;
float *angles;
int *ucvGray;

float *hist[6];
float *channels[10];
int *acf_channels[10];

int mW,mH,dimensions;
float *mLUV;
float *ucvGradMag;
}
在C#中将其对应成了如下形式:
public struct ucvACF
{
public int mW;
public int mH;
public int dimensions;
public IntPtr mLUV;
public IntPtr ucvGradMag;
public IntPtr ucvTemp;
public IntPtr ucvGx;
public IntPtr ucvGy;
public IntPtr angles;
public IntPtr ucvGray;
//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
public IntPtr hist;
//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public IntPtr channels;
// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public IntPtr acf_channels;
}
然后通过 Marshal.StructureToPtr(myucvACF, ptr1, true) 将结构体传到了函数内部,可是运行结果不正确,追踪到dll内部发现dll内的数据是正确的,可是通过System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes)将mLUV中的数据考到luv中时,数据是错误的,请问各位大神是怎么回事????
...全文
525 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
_lee_chong 2015-08-21
  • 打赏
  • 举报
回复
引用 27 楼 tianxiaoying22 的回复:
[quote=引用 26 楼 lc316546079 的回复:] [quote=引用 24 楼 tianxiaoying22 的回复:] [quote=引用 22 楼 lc316546079 的回复:] 如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错; 你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致; 如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
dll中mluv的前五个数分别为,70 29 84 70 29;bytes中为11 219 141 66 8。这有什么规律在里边吗,我实在看不出来。[/quote] 一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据, 在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点 查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致; 在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错[/quote] C#可以看内存吗?我怎么看不了,查了一下好像说不让看[/quote] 。。。。谁说不让看。。。我在mac下没有vs不能截图,但是“菜单 调试->窗口->内存”这样打开的调试窗口是可以看内存的,大概菜单式这么点,没vs在手上我也不确定你去菜单里找找
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
引用 22 楼 lc316546079 的回复:
如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错; 你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致; 如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
两个地址一样,但是两个数据完全不一样,dll中mluv的数据是正确的,bytes里不对
_lee_chong 2015-08-20
  • 打赏
  • 举报
回复
如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错; 你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致; 如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
wanghui0380 2015-08-20
  • 打赏
  • 举报
回复
BitmapData 设置好宽高,范围后。直接把Scan0 的指针指向到你获取到的那个intptr上看看
wanghui0380 2015-08-20
  • 打赏
  • 举报
回复
有关你最后一个问题,inptr只是一个指针,按照你的东西,我觉着你可以使用BitmapData去接收
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
引用 10 楼 sp1234 的回复:
c++中的指针,意味着可能“胡写乱写,并没有确定的最终含义。 既然是可以协作的,那么凡是这种接口应该让底层的c++程序员去写,并且调试通过。或者让c#程序原来按照自己的要求制定接口规范,然后c++程序去实现。
大家没有人懂C#。。。。。都是用C/C++ 我昨天代码贴错了,两个结构体顺序一致,现在问题是这样的,我追到dll里边,发现dll里的数据正确,所以我觉得应该在向外拷数据的时候出的错,我是通过下面的方法将mluv里的数据考到图片中的 int bytes = curBitmap.Width * curBitmap.Height * 3; byte[] luv = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes); System.Runtime.InteropServices.Marshal.Copy(luv, 0, ptr, bytes);//其中ptr是Tntptr类型,指向图片首地址 如果用C/C++的话是这样操作的 for (int i = 0; i < height; i++) { for (int j = 0; j < widthStep; j += step) { im.data[i*widthStep+j] = (unsigned char)UucvACF->mluv[i*widthStep+j]; im.data[i*widthStep+j+1] = (unsigned char)UucvACF->mluv[i*widthStep+j+1]; im.data[i*widthStep+j+2] = (unsigned char)UucvACF->mluv[i*widthStep+j+2]; } } 结果是C#中的luv里的数据和C中im.data[]里的数据不一样,我在想是不是copy()出了错,或者是类型对应有错误 您觉得是什么原因呢
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
引用 16 楼 wanghui0380 的回复:
这得按顺序啊,封送过程其实就是内存数据传递 所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct ucvACF {
    
    /// float*
    public System.IntPtr ucvTemp;
    
    /// float*
    public System.IntPtr ucvGx;
    
    /// float*
    public System.IntPtr ucvGy;
    
    /// float*
    public System.IntPtr angles;
    
    /// int*
    public System.IntPtr ucvGray;
    
    /// float*[6]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=6, ArraySubType=System.Runtime.InteropServices.UnmanagedType.SysUInt)]
    public System.IntPtr[] hist;
    
    /// float*[10]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=10, ArraySubType=System.Runtime.InteropServices.UnmanagedType.SysUInt)]
    public System.IntPtr[] channels;
    
    /// int*[10]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=10, ArraySubType=System.Runtime.InteropServices.UnmanagedType.SysUInt)]
    public System.IntPtr[] acf_channels;
    
    /// int
    public int mW;
    
    /// int
    public int mH;
    
    /// int
    public int dimensions;
    
    /// float*
    public System.IntPtr mLUV;
    
    /// float*
    public System.IntPtr ucvGradMag;
}
不好意思我代码贴错了,现在的问题是这个: 我追到dll里边,发现dll里的数据正确,所以我觉得应该在向外拷数据的时候出的错,我是通过下面的方法将mluv里的数据考到图片中的 int bytes = curBitmap.Width * curBitmap.Height * 3; byte[] luv = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes); System.Runtime.InteropServices.Marshal.Copy(luv, 0, ptr, bytes);//其中ptr是Tntptr类型,指向图片首地址 如果用C/C++的话是这样操作的 for (int i = 0; i < height; i++) { for (int j = 0; j < widthStep; j += step) { im.data[i*widthStep+j] = (unsigned char)UucvACF->mluv[i*widthStep+j]; im.data[i*widthStep+j+1] = (unsigned char)UucvACF->mluv[i*widthStep+j+1]; im.data[i*widthStep+j+2] = (unsigned char)UucvACF->mluv[i*widthStep+j+2]; } } 结果是C#中的luv里的数据和C中im.data[]里的数据不一样,我在想是不是copy()出了错,或者是类型对应有错误
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
不好意思各位,我C的代码贴错了,顺序一样, typedef struct ucvACF { int mW,mH,dimensions; float *mLUV; float *ucvGradMag; float *ucvTemp; float *ucvGx; float *ucvGy; float *angles; int *ucvGray; float *hist[6]; float *channels[10]; int *acf_channels[10]; }
wanghui0380 2015-08-20
  • 打赏
  • 举报
回复
这得按顺序啊,封送过程其实就是内存数据传递 所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct ucvACF {
    
    /// float*
    public System.IntPtr ucvTemp;
    
    /// float*
    public System.IntPtr ucvGx;
    
    /// float*
    public System.IntPtr ucvGy;
    
    /// float*
    public System.IntPtr angles;
    
    /// int*
    public System.IntPtr ucvGray;
    
    /// float*[6]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=6, ArraySubType=System.Runtime.InteropServices.UnmanagedType.SysUInt)]
    public System.IntPtr[] hist;
    
    /// float*[10]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=10, ArraySubType=System.Runtime.InteropServices.UnmanagedType.SysUInt)]
    public System.IntPtr[] channels;
    
    /// int*[10]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=10, ArraySubType=System.Runtime.InteropServices.UnmanagedType.SysUInt)]
    public System.IntPtr[] acf_channels;
    
    /// int
    public int mW;
    
    /// int
    public int mH;
    
    /// int
    public int dimensions;
    
    /// float*
    public System.IntPtr mLUV;
    
    /// float*
    public System.IntPtr ucvGradMag;
}
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
引用 14 楼 bigbaldy 的回复:
C#中全用指针即可,取值也用指针,操作方便简单,目前我还没遇到过不能成功的结构体
什么叫取值也用指针,我昨天代码贴错了,结构体顺序是一致的,穿进去了,dll里的数据也正确,所以我觉得应该在向外拷数据的时候出的错,我是通过下面的方法将mluv里的数据考到图片中的 int bytes = curBitmap.Width * curBitmap.Height * 3; byte[] luv = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes); System.Runtime.InteropServices.Marshal.Copy(luv, 0, ptr, bytes);//其中ptr是Tntptr类型,指向图片首地址 如果用C/C++的话是这样操作的 for (int i = 0; i < height; i++) { for (int j = 0; j < widthStep; j += step) { im.data[i*widthStep+j] = (unsigned char)UucvACF->mluv[i*widthStep+j]; im.data[i*widthStep+j+1] = (unsigned char)UucvACF->mluv[i*widthStep+j+1]; im.data[i*widthStep+j+2] = (unsigned char)UucvACF->mluv[i*widthStep+j+2]; } } 结果是C#中的luv里的数据和C中im.data[]里的数据不一样,我在想是不是copy()出了错,或者是类型对应有错误 谢谢各位了
bigbaldy 2015-08-20
  • 打赏
  • 举报
回复
C#中全用指针即可,取值也用指针,操作方便简单,目前我还没遇到过不能成功的结构体
_lee_chong 2015-08-20
  • 打赏
  • 举报
回复
要改很多东西? 且不谈那么多指针,就算在c/c++中管理内存会稍显麻烦; 就c#的使用来说全是intptr每次的get要 ptr to struct,每次set要struct to ptr.........累。。。 还有那数组。。。。c#的数组在堆里结构体只保留指针,c/c++那数组是实际存放在结构体里。。。 c++提供给c#的接口,最好要c# c/c++都了解的人来封装更合适,里面更多的是c#的认识,我的建议是由一个 真正 熟悉c#且了解c/c++的人来定义及封装;如果没有,那就让你自己做那个人。。。 另外我提议你获取两边的size意思是让你明白两边结构体并不对应,根据差多少字节,去思考了解c# c/c++关于结构体在内存中的存放原理。
jie3500 2015-08-20
  • 打赏
  • 举报
回复
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
引用 26 楼 lc316546079 的回复:
[quote=引用 24 楼 tianxiaoying22 的回复:] [quote=引用 22 楼 lc316546079 的回复:] 如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错; 你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致; 如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
dll中mluv的前五个数分别为,70 29 84 70 29;bytes中为11 219 141 66 8。这有什么规律在里边吗,我实在看不出来。[/quote] 一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据, 在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点 查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致; 在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错[/quote] C#可以看内存吗?我怎么看不了,查了一下好像说不让看
_lee_chong 2015-08-20
  • 打赏
  • 举报
回复
引用 24 楼 tianxiaoying22 的回复:
[quote=引用 22 楼 lc316546079 的回复:] 如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错; 你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致; 如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
dll中mluv的前五个数分别为,70 29 84 70 29;bytes中为11 219 141 66 8。这有什么规律在里边吗,我实在看不出来。[/quote] 一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据, 在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点 查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致; 在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
引用 21 楼 wanghui0380 的回复:
BitmapData 设置好宽高,范围后。直接把Scan0 的指针指向到你获取到的那个intptr上看看
我的ptr本来是指向原图的Scan0,现在我ptr = myucvACF1.mLUV,结果输出原图,没有变;;可是我用上边的方法,结果是雪花,这是什么原因
tianxiaoying22 2015-08-20
  • 打赏
  • 举报
回复
引用 22 楼 lc316546079 的回复:
如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错; 你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致; 如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
dll中mluv的前五个数分别为,70 29 84 70 29;bytes中为11 219 141 66 8。这有什么规律在里边吗,我实在看不出来。
tianxiaoying22 2015-08-19
  • 打赏
  • 举报
回复
引用 11 楼 sp1234 的回复:
[quote=引用 8 楼 tianxiaoying22 的回复:] dll中不用计算这个的大小,直接传结构体指针就行了,不过我用C在外面定义了一个一样的结构体试了一下,两个大小还真不一样。代码是师兄给的,只说让我用C#搭界面,方
从你贴出的两段代码可以看出来,你连 顺序都不一样,说明你不是从c++那种比较低级的面向字节顺序的角度去理解c++,而是从c#的高级的面向类型的角度去理解c++。你现在还没有理解c和c++语言啊。[/quote] 额 我大学学的不是计算机,只在大一简单的学过几天C, 所以.........
  • 打赏
  • 举报
回复
引用 8 楼 tianxiaoying22 的回复:
dll中不用计算这个的大小,直接传结构体指针就行了,不过我用C在外面定义了一个一样的结构体试了一下,两个大小还真不一样。代码是师兄给的,只说让我用C#搭界面,方
从你贴出的两段代码可以看出来,你连 顺序都不一样,说明你不是从c++那种比较低级的面向字节顺序的角度去理解c++,而是从c#的高级的面向类型的角度去理解c++。你现在还没有理解c和c++语言啊。
  • 打赏
  • 举报
回复
c++中的指针,意味着可能“胡写乱写,并没有确定的最终含义。 既然是可以协作的,那么凡是这种接口应该让底层的c++程序员去写,并且调试通过。或者让c#程序原来按照自己的要求制定接口规范,然后c++程序去实现。
加载更多回复(9)

110,477

社区成员

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

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

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