gpt4 book ai didi

c# - 如果没有调试器,来自 C# interop 的 OpenCv 卡在 cvSaveImage 上!

转载 作者:太空宇宙 更新时间:2023-11-03 21:28:35 25 4
gpt4 key购买 nike

大家 -- 我有一个 Heisenbug,在这里(只显示分离调试器!​​)。似乎在 C# 中与非托管互操作——如果我对 %TEMP% 目录执行 OpenCv cvSaveImage,没问题,但对于我尝试过的其他目录,它会抛出 AccVio 或挂起。以管理员身份运行,因此不是直接的安全问题。在 C# Visual Studio 2010 调试器下运行,它适用于任何目录。调试器分离 (ctrl F5) ... 崩溃或挂起!访问。

如有任何建议,我将不胜感激。我知道你们中的一些人在这个互操作层上生活和呼吸,但我没有工具和足够新的经验。我做了一个非常小的复制品供你玩

必须使用默认值安装 OpenCv2.2 [免费图像处理和计算机视觉 (cv)](2010 年 12 月版),来自 sourceforge.net/projects/opencvlibrary/

然后从 http://dl.dropbox.com/u/1997638/OpenCv2.2Test.zip 中选取我的 Visual Studio 2010 项目

它有包装器(感谢 Heiko Kießling,iib-chemnitz.de 的原创!)和一个带有注释的测试程序,可指导您找到可重复的错误。

再一次,如果有任何建议或线索,我将不胜感激!

编辑:@Aliostad:这是整个程序(减去包装器,它在我链接的 VS 项目中)

        static void Main(string[] args)
{
CvLib.CvNamedWindow("TestWindow2", CvLib.CV_WINDOW_AUTOSIZE);

var img = CvLib.CvCreateImage(
CvLib.CvSize(256, 256),
depth: 8,
channels: 3);

var pts = new[] {
CvLib.CvPoint(0, 0),
CvLib.CvPoint(0, 255),
CvLib.CvPoint(255,255),
CvLib.CvPoint(255, 0)
};

CvLib.CvFillConvexPoly(
img: ref img,
pts: ref pts[0],
npts: 4,
color: CvLib.CV_RGB(0, 0, 255),
line_type: 8,
shift: 0);

CvLib.CvCircle(
img: ref img,
center: CvLib.CvPoint(128, 128),
radius: 20,
color: CvLib.CV_RGB(255, 255, 0),
thickness: 5,
line_type: 8,
shift: 0);

CvLib.CvShowImage(
name: "TestWindow2",
image: ref img);

var tempDirectory = Environment.GetEnvironmentVariable("TEMP");
var path = tempDirectory + @"\test.png";

CvLib.CvSaveImage(
path: path,
img: ref img);

MessageBox.Show("Click OK to exit");
CvLib.CvDestroyAllWindows();
}

在未连接调试器时将“路径”更改为任何其他内容会导致崩溃或挂起。

编辑:@Aliostad——这里是 cvSaveImage 的互操作代码。我确定我不理解 MarshalAs 属性,我猜这是问题的根源

        public static void CvSaveImage(string path, ref IplImage img)
{
cvSaveImage(path, img.ptr);
}
[DllImport(HIGHGUI_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
private static extern void cvSaveImage([MarshalAs(UnmanagedType.LPStr)] String filename, IntPtr img);

最佳答案

这是从 highgui.h 中检索到的 native cvSaveImage() 函数的声明:

CVAPI(int) cvSaveImage( const char* filename, const CvArr* image,
const int* params CV_DEFAULT(0) );

这是它的 pinvoke 声明,从包装器 HighGui.cs 中检索:

    [DllImport(HIGHGUI_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
private static extern void cvSaveImage([MarshalAs(UnmanagedType.LPStr)] String filename, IntPtr img);

请注意 native 声明如何具有三个 参数,而 pinvoke 声明只有两个。可以从 C++ 程序调用 native 函数并仅传递两个参数,编译器会自动为第三个参数应用默认值。但这对 pinvoke 编码器不起作用,它甚至不知道第三个参数是否存在。

结果是 native 函数为 params 参数获取任意值。当它不小心为 0 时它起作用。但是函数还有 40 亿种其他方法来获取非 null 参数,并在取消引用指针时立即处理访问冲突。失败是随机的。

通过编辑 pinvoke 声明并添加一个 IntPtr 作为第三个参数来解决这个问题。在 C# 代码中传递 IntPtr.Zero。

这是一个相当基本的错误,这个包装器会带来更多麻烦。

关于c# - 如果没有调试器,来自 C# interop 的 OpenCv 卡在 cvSaveImage 上!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4513787/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com