首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果没有调试器,来自C#互操作的OpenCv在cvSaveImage上挂起!

如果没有调试器,来自C#互操作的OpenCv在cvSaveImage上挂起!
EN

Stack Overflow用户
提问于 2010-12-23 05:12:25
回答 1查看 1.5K关注 0票数 2

每个人--我这里有一个Heisenbug (只在调试器分离的情况下出现!)。似乎在非托管互操作的C#中--如果我对%TEMP%目录执行OpenCv cvSaveImage,这是可以的,但对于我尝试过的其他目录,它会抛出AccVio或挂起。以管理员身份运行,因此不会直接成为安全问题。在C# Visual Studio2010调试器下运行,它在任何目录下都可以正常工作。已分离调试器(ctrl F5) ...崩溃或挂起!好的。

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

必须使用默认设置从sourceforge.net/ free image processing and computer vision (cv) /opencvlibrary/安装OpenCv2.2项目

然后从http://dl.dropbox.com/u/1997638/OpenCv2.2Test.zip获取我的Visual Studio2010项目

这是一个包装器(感谢Heiko Kieüling,iib-chemnitz.de for the original!)以及一个带有注释的测试程序,这些注释可以指导您找到可重复的bug。

再一次,我将非常感谢任何建议或线索!

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

代码语言:javascript
复制
        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();
    }

如果将"path“更改为其他值,则会在未附加调试器时导致崩溃或挂起。

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

代码语言:javascript
复制
        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);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-12-25 01:34:19

这是原生cvSaveImage()函数的声明,从Highgui.h检索:

代码语言:javascript
复制
CVAPI(int) cvSaveImage( const char* filename, const CvArr* image,
                        const int* params CV_DEFAULT(0) );

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

代码语言:javascript
复制
    [DllImport(HIGHGUI_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
    private static extern void cvSaveImage([MarshalAs(UnmanagedType.LPStr)] String filename, IntPtr img);

请注意,本机声明有三个参数,而pinvoke声明只有两个。可以从C++程序调用本机函数,并且只传递两个参数,编译器会自动将默认值应用于第三个参数。但对于pinvoke编组程序,这不是这样的,它甚至不知道第三个参数是否存在。

结果是本机函数获得params参数的任意值。当它意外地为0时,它会起作用。但是,该函数还有40亿种其他方法来获取非空参数,并在取消引用指针时直接访问冲突。失败将是随机的。

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

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4513787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档