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中时,数据是错误的,请问各位大神是怎么回事????
29 个解决方案
#1
[StructLayout(LayoutKind.Sequential)]
public struct ucvACF
{
public IntPtr ucvTemp;
public IntPtr ucvGx;
public IntPtr ucvGy;
public IntPtr angles;
public IntPtr ucvGray;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public IntPtr[] hist;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public IntPtr[] channels;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public IntPtr[] acf_channels;
public int mW;
public int mH;
public int dimensions;
public IntPtr mLUV;
public IntPtr ucvGradMag;
}
你这c++原型是哪家孩子写的,如果是专门写来和c#交互的,那写的真是够了,否则就罢了
#2
你写的结构体和c++里完全不同,至少顺序要一样,结构体要加上[StructLayout(LayoutKind.Sequential)]
#3
建议换成System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, floats)
#4
本来那么写 追踪到dll里的数据还是对的,结构改成这种形式后dll中结构体内的数据都不对
#5
本来会对,才奇怪了,
发代码吧
发代码吧
#6
private unsafe void luv_Click(object sender, EventArgs e)
{
if (curBitmap != null)
{
myTimer.ClearTimer();
myTimer.Start();
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);//获得感兴趣区,前边是坐标,后边是大小
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);//锁定感兴趣区,只能在此区域操作(第二个参数指明可以进行何种操作)
IntPtr ptr = bmpData.Scan0;//获取第一行地址
ucvACF myucvACF = new ucvACF();
myucvACF.mW = curBitmap.Width;
myucvACF.mH = curBitmap.Height;
myucvACF.dimensions = 3;
//将结构体转换为指针
int size = Marshal.SizeOf(myucvACF);
byte[] buf = new byte[size];
IntPtr ptr1 = Marshal.AllocHGlobal(size);//分配结构体大小的空间
Marshal.StructureToPtr(myucvACF, ptr1, true);//将结构体拷到分配好的内存空间
MallocChannels(ptr1);//dll中函数,主要在分配内存
for(int i=0;i<10;i++){
FeatureCompute(ptr1, ptr);//dll中函数,进行图像的一些处理
}
//指针转回结构体
ucvACF myucvACF1;
myucvACF1 = (ucvACF)Marshal.PtrToStructure(ptr1, typeof(ucvACF));
//定义一个数组保存图片
int bytes = curBitmap.Width * curBitmap.Height * 3;
byte[] luv = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);//复制RGB的值到所声明的数组中
System.Runtime.InteropServices.Marshal.Copy(luv, 0, ptr, bytes);
curBitmap.UnlockBits(bmpData);
myTimer.Stop();
timeBox.Text = myTimer.Duration.ToString("####.##") + " 毫秒";
Invalidate();
}
}
#7
你这里获得的size是多少
int size = Marshal.SizeOf(myucvACF);
dll中 sizeof(ucvACF)获得的大小又是多少;
-----------------------
既然你说你追踪到了dll里的数据,说明你有dll的源码,建议把这个结构体改了,弄那么多指针干什么,c#操作起来那么麻烦
int size = Marshal.SizeOf(myucvACF);
dll中 sizeof(ucvACF)获得的大小又是多少;
-----------------------
既然你说你追踪到了dll里的数据,说明你有dll的源码,建议把这个结构体改了,弄那么多指针干什么,c#操作起来那么麻烦
#8
dll中不用计算这个的大小,直接传结构体指针就行了,不过我用C在外面定义了一个一样的结构体试了一下,两个大小还真不一样。代码是师兄给的,只说让我用C#搭界面,如果把那个结构体改了,得改好多地方
#9
如果你师兄不能给封装个c#的接口,并且测试通过,那么你就换一个项目吧。
#10
c++中的指针,意味着可能“胡写乱写,并没有确定的最终含义。
既然是可以协作的,那么凡是这种接口应该让底层的c++程序员去写,并且调试通过。或者让c#程序原来按照自己的要求制定接口规范,然后c++程序去实现。
既然是可以协作的,那么凡是这种接口应该让底层的c++程序员去写,并且调试通过。或者让c#程序原来按照自己的要求制定接口规范,然后c++程序去实现。
#11
从你贴出的两段代码可以看出来,你连 顺序都不一样,说明你不是从c++那种比较低级的面向字节顺序的角度去理解c++,而是从c#的高级的面向类型的角度去理解c++。你现在还没有理解c和c++语言啊。
#12
额 我大学学的不是计算机,只在大一简单的学过几天C, 所以.........
#13
要改很多东西?
且不谈那么多指针,就算在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++关于结构体在内存中的存放原理。
且不谈那么多指针,就算在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++关于结构体在内存中的存放原理。
#14
C#中全用指针即可,取值也用指针,操作方便简单,目前我还没遇到过不能成功的结构体
#15
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()出了错,或者是类型对应有错误
谢谢各位了
#16
这得按顺序啊,封送过程其实就是内存数据传递
所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了
所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了
[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;
}
#17
不好意思各位,我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];
}
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];
}
#18
这得按顺序啊,封送过程其实就是内存数据传递
所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了[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()出了错,或者是类型对应有错误
#19
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()出了错,或者是类型对应有错误
您觉得是什么原因呢
#20
有关你最后一个问题,inptr只是一个指针,按照你的东西,我觉着你可以使用BitmapData去接收
#21
BitmapData 设置好宽高,范围后。直接把Scan0 的指针指向到你获取到的那个intptr上看看
#22
如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错;
你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致;
如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致;
如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
#23
如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错;
你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致;
如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
两个地址一样,但是两个数据完全不一样,dll中mluv的数据是正确的,bytes里不对
#24
如果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。这有什么规律在里边吗,我实在看不出来。
#25
BitmapData 设置好宽高,范围后。直接把Scan0 的指针指向到你获取到的那个intptr上看看
我的ptr本来是指向原图的Scan0,现在我ptr = myucvACF1.mLUV,结果输出原图,没有变;;可是我用上边的方法,结果是雪花,这是什么原因
#26
如果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。这有什么规律在里边吗,我实在看不出来。
一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据,
在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点
查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致;
在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错
#27
如果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。这有什么规律在里边吗,我实在看不出来。
一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据,
在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点
查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致;
在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错
C#可以看内存吗?我怎么看不了,查了一下好像说不让看
#28
#29
如果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。这有什么规律在里边吗,我实在看不出来。
一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据,
在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点
查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致;
在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错
C#可以看内存吗?我怎么看不了,查了一下好像说不让看
。。。。谁说不让看。。。我在mac下没有vs不能截图,但是“菜单 调试->窗口->内存”这样打开的调试窗口是可以看内存的,大概菜单式这么点,没vs在手上我也不确定你去菜单里找找
#1
[StructLayout(LayoutKind.Sequential)]
public struct ucvACF
{
public IntPtr ucvTemp;
public IntPtr ucvGx;
public IntPtr ucvGy;
public IntPtr angles;
public IntPtr ucvGray;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public IntPtr[] hist;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public IntPtr[] channels;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public IntPtr[] acf_channels;
public int mW;
public int mH;
public int dimensions;
public IntPtr mLUV;
public IntPtr ucvGradMag;
}
你这c++原型是哪家孩子写的,如果是专门写来和c#交互的,那写的真是够了,否则就罢了
#2
你写的结构体和c++里完全不同,至少顺序要一样,结构体要加上[StructLayout(LayoutKind.Sequential)]
#3
建议换成System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, floats)
#4
[StructLayout(LayoutKind.Sequential)]
public struct ucvACF
{
public IntPtr ucvTemp;
public IntPtr ucvGx;
public IntPtr ucvGy;
public IntPtr angles;
public IntPtr ucvGray;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public IntPtr[] hist;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public IntPtr[] channels;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public IntPtr[] acf_channels;
public int mW;
public int mH;
public int dimensions;
public IntPtr mLUV;
public IntPtr ucvGradMag;
}
你这c++原型是哪家孩子写的,如果是专门写来和c#交互的,那写的真是够了,否则就罢了
本来那么写 追踪到dll里的数据还是对的,结构改成这种形式后dll中结构体内的数据都不对
#5
本来会对,才奇怪了,
发代码吧
发代码吧
#6
本来会对,才奇怪了,
发代码吧
private unsafe void luv_Click(object sender, EventArgs e)
{
if (curBitmap != null)
{
myTimer.ClearTimer();
myTimer.Start();
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);//获得感兴趣区,前边是坐标,后边是大小
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);//锁定感兴趣区,只能在此区域操作(第二个参数指明可以进行何种操作)
IntPtr ptr = bmpData.Scan0;//获取第一行地址
ucvACF myucvACF = new ucvACF();
myucvACF.mW = curBitmap.Width;
myucvACF.mH = curBitmap.Height;
myucvACF.dimensions = 3;
//将结构体转换为指针
int size = Marshal.SizeOf(myucvACF);
byte[] buf = new byte[size];
IntPtr ptr1 = Marshal.AllocHGlobal(size);//分配结构体大小的空间
Marshal.StructureToPtr(myucvACF, ptr1, true);//将结构体拷到分配好的内存空间
MallocChannels(ptr1);//dll中函数,主要在分配内存
for(int i=0;i<10;i++){
FeatureCompute(ptr1, ptr);//dll中函数,进行图像的一些处理
}
//指针转回结构体
ucvACF myucvACF1;
myucvACF1 = (ucvACF)Marshal.PtrToStructure(ptr1, typeof(ucvACF));
//定义一个数组保存图片
int bytes = curBitmap.Width * curBitmap.Height * 3;
byte[] luv = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);//复制RGB的值到所声明的数组中
System.Runtime.InteropServices.Marshal.Copy(luv, 0, ptr, bytes);
curBitmap.UnlockBits(bmpData);
myTimer.Stop();
timeBox.Text = myTimer.Duration.ToString("####.##") + " 毫秒";
Invalidate();
}
}
#7
你这里获得的size是多少
int size = Marshal.SizeOf(myucvACF);
dll中 sizeof(ucvACF)获得的大小又是多少;
-----------------------
既然你说你追踪到了dll里的数据,说明你有dll的源码,建议把这个结构体改了,弄那么多指针干什么,c#操作起来那么麻烦
int size = Marshal.SizeOf(myucvACF);
dll中 sizeof(ucvACF)获得的大小又是多少;
-----------------------
既然你说你追踪到了dll里的数据,说明你有dll的源码,建议把这个结构体改了,弄那么多指针干什么,c#操作起来那么麻烦
#8
你这里获得的size是多少
int size = Marshal.SizeOf(myucvACF);
dll中 sizeof(ucvACF)获得的大小又是多少;
-----------------------
既然你说你追踪到了dll里的数据,说明你有dll的源码,建议把这个结构体改了,弄那么多指针干什么,c#操作起来那么麻烦
dll中不用计算这个的大小,直接传结构体指针就行了,不过我用C在外面定义了一个一样的结构体试了一下,两个大小还真不一样。代码是师兄给的,只说让我用C#搭界面,如果把那个结构体改了,得改好多地方
#9
如果你师兄不能给封装个c#的接口,并且测试通过,那么你就换一个项目吧。
#10
c++中的指针,意味着可能“胡写乱写,并没有确定的最终含义。
既然是可以协作的,那么凡是这种接口应该让底层的c++程序员去写,并且调试通过。或者让c#程序原来按照自己的要求制定接口规范,然后c++程序去实现。
既然是可以协作的,那么凡是这种接口应该让底层的c++程序员去写,并且调试通过。或者让c#程序原来按照自己的要求制定接口规范,然后c++程序去实现。
#11
dll中不用计算这个的大小,直接传结构体指针就行了,不过我用C在外面定义了一个一样的结构体试了一下,两个大小还真不一样。代码是师兄给的,只说让我用C#搭界面,方
从你贴出的两段代码可以看出来,你连 顺序都不一样,说明你不是从c++那种比较低级的面向字节顺序的角度去理解c++,而是从c#的高级的面向类型的角度去理解c++。你现在还没有理解c和c++语言啊。
#12
dll中不用计算这个的大小,直接传结构体指针就行了,不过我用C在外面定义了一个一样的结构体试了一下,两个大小还真不一样。代码是师兄给的,只说让我用C#搭界面,方
从你贴出的两段代码可以看出来,你连 顺序都不一样,说明你不是从c++那种比较低级的面向字节顺序的角度去理解c++,而是从c#的高级的面向类型的角度去理解c++。你现在还没有理解c和c++语言啊。
额 我大学学的不是计算机,只在大一简单的学过几天C, 所以.........
#13
要改很多东西?
且不谈那么多指针,就算在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++关于结构体在内存中的存放原理。
且不谈那么多指针,就算在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++关于结构体在内存中的存放原理。
#14
C#中全用指针即可,取值也用指针,操作方便简单,目前我还没遇到过不能成功的结构体
#15
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()出了错,或者是类型对应有错误
谢谢各位了
#16
这得按顺序啊,封送过程其实就是内存数据传递
所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了
所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了
[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;
}
#17
不好意思各位,我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];
}
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];
}
#18
这得按顺序啊,封送过程其实就是内存数据传递
所以,你内存顺序不同,结果自然不可知。话说你这样乱串居然没木溢出也算是个小奇迹了[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()出了错,或者是类型对应有错误
#19
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()出了错,或者是类型对应有错误
您觉得是什么原因呢
#20
有关你最后一个问题,inptr只是一个指针,按照你的东西,我觉着你可以使用BitmapData去接收
#21
BitmapData 设置好宽高,范围后。直接把Scan0 的指针指向到你获取到的那个intptr上看看
#22
如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错;
你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致;
如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致;
如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
#23
如果c++ 那段代码里 widthStep 是 width *3 且 step 是3的话,那你这样copy就不该有错;
你可以先在dll中看mLUV指向的地址是多少,再在c#中看是多少,对比是否一致;
如果一致,再拿copy以后bytes里的数据,和dll中mLUV数据做对比看怎么个不一样法
两个地址一样,但是两个数据完全不一样,dll中mluv的数据是正确的,bytes里不对
#24
如果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。这有什么规律在里边吗,我实在看不出来。
#25
BitmapData 设置好宽高,范围后。直接把Scan0 的指针指向到你获取到的那个intptr上看看
我的ptr本来是指向原图的Scan0,现在我ptr = myucvACF1.mLUV,结果输出原图,没有变;;可是我用上边的方法,结果是雪花,这是什么原因
#26
如果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。这有什么规律在里边吗,我实在看不出来。
一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据,
在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点
查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致;
在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错
#27
如果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。这有什么规律在里边吗,我实在看不出来。
一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据,
在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点
查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致;
在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错
C#可以看内存吗?我怎么看不了,查了一下好像说不让看
#28
#29
如果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。这有什么规律在里边吗,我实在看不出来。
一步一步找错,既然你说dll 里看到的 mLUVd地址和c#里看到的一样,那就比数据,
在System.Runtime.InteropServices.Marshal.Copy(myucvACF1.mLUV, luv, 0, bytes);断点
查看myucvACF1.mLUV地址,复制, 去菜单的 调试->窗口->内存 里查看该地址的数据,和dll中时 mLUV是否一致;
在地址一致时,数据肯定也是一致的,如果不对,只能是你哪里细节说错了,且你自认为没错
C#可以看内存吗?我怎么看不了,查了一下好像说不让看
。。。。谁说不让看。。。我在mac下没有vs不能截图,但是“菜单 调试->窗口->内存”这样打开的调试窗口是可以看内存的,大概菜单式这么点,没vs在手上我也不确定你去菜单里找找