PInvoke - 从C#代码调用DJVU函数时出现问题。尝试读取或写入受保护的内存

时间:2015-03-04 13:15:29

标签: pinvoke djvu

更新3-4-15:11IS 正如David修改PInvoke所建议的那样,这次我得到了不同的错误" mscorlib.dll中发生了System.ExecutionEngineException类型的未处理异常"

    [DllImport("C:\\Program Files\\DJVULIBRE\\LIBDJVULIBRE.dll", CharSet=CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    private unsafe static extern int ddjvu_page_render(IntPtr page, ddjvu_render_mode_t mode, ref ddjvu_rect_t pagerect,
              ref ddjvu_rect_t renderrect,
              IntPtr pixelformat,
              uint rowsize,
              [Out][MarshalAs(UnmanagedType.LPArray)]byte[] imagebuffer);

感谢大卫宝贵的时间,我认为已接近修复。

记录

我知道这个问题有很多问题,但没有一个问题有助于解决我目前面临的问题。

以下是C语言中的API函数

DDJVUAPI int
ddjvu_page_render(ddjvu_page_t *page,
                  const ddjvu_render_mode_t mode,
                  const ddjvu_rect_t *pagerect,
                  const ddjvu_rect_t *renderrect,
                  const ddjvu_format_t *pixelformat,
                  unsigned long rowsize,
                  char *imagebuffer );

下面是在.NET代码中添加的C函数的PInvoke签名

[DllImport("C:\\Program Files\\DJVULIBRE\\LIBDJVULIBRE.dll", CharSet=CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern int ddjvu_page_render(IntPtr page, ddjvu_render_mode_t mode, IntPtr pagerect,
          IntPtr renderrect,
          IntPtr pixelformat,
          ulong rowsize,
          [Out][MarshalAs(UnmanagedType.LPArray)]byte[] imagebuffer);

以下是我在c#代码中调用此函数的方法

            byte* buffer = (byte *)Memory.Alloc(nSize);
            try
            {
                IntPtr ptr1 = (IntPtr)Memory.Alloc(Marshal.SizeOf(prect));
                Marshal.StructureToPtr(prect, ptr1, false);

                IntPtr ptr2 = (IntPtr)Memory.Alloc(Marshal.SizeOf(rrect));
                Marshal.StructureToPtr(rrect, ptr2, false);

                byte[] array = new byte[nSize];
                fixed (byte* p = array) Memory.Copy(buffer, p, nSize);
                ddjvu_page_render(page, ddjvu_render_mode_t.DDJVU_RENDER_MASKONLY, ptr1, ptr2, fmt, (ulong)stride, array);
            }
            finally
            {
                Memory.Free(buffer);
            }

在上面的代码中调用ddjvu_page_render正在抛出"尝试读取或写入受保护的内存。这通常表明其他内存已损坏。" 在这篇文章之前,我必须尝试在各种博客中找到的所有选项。 感谢任何帮助,几乎是一天我无能为力,你的及时帮助可以挽救我的工作

更新3-4-15:7:44IS 此代码使用DJVULibre

更新3-4-15:8:35IS

这是我在Form Load

中的代码
    ctx = ddjvu_context_create(System.AppDomain.CurrentDomain.FriendlyName);
    if (ctx != null)
    {
        string djFile = "C:\\Users\\rammohan.chavakula\\Documents\\eiasample.djvu";
        doc = ddjvu_document_create_by_filename(ctx, djFile, 100);
        if (doc != null)
        {
            while (ddjvu_job_status(ddjvu_document_job(doc)) >= ddjvu_status_t.DDJVU_JOB_OK)
                SpinDdjvuMessageLoop(ctx, true);

            int pageCount = ddjvu_document_get_pagenum(doc);
            mediaboxes =  new Rectangle[pageCount];
            for (int i = 0; i < pageCount; i++)
            {
                ddjvu_status_t status;
                ddjvu_pageinfo_t info = new ddjvu_pageinfo_t();

                while ((status = ddjvu_document_get_pageinfo_imp(doc, i, ref info, (uint)System.Runtime.InteropServices.Marshal.SizeOf(info))) < ddjvu_status_t.DDJVU_JOB_OK)
                    SpinDdjvuMessageLoop(ctx, true);
                if (status != ddjvu_status_t.DDJVU_JOB_OK)
                    continue;

                mediaboxes[i] = new Rectangle(0, 0, info.width / info.dpi,
                            info.height / info.dpi);

            }

        }
        ddjvu_context_release(ctx);
    }

在OnPaint功能中,我有以下代码

        if (doc == null)
        {
            base.OnPaint(e);
            return;
        }
        Rectangle pageRc = PageMediabox(1);
        Rectangle screen = Transform(pageRc, 1, zoom, rotation, false);
        Rectangle full = Transform(PageMediabox(1), 1, zoom, rotation, false);
        full.Intersect(screen);

        IntPtr page = ddjvu_page_create_by_pageno(doc, 1);
        if (page == null )
        {
            base.OnPaint(e);
            return;
        }
        int rotation4 = (((-rotation / 90) % 4) + 4) % 4;
        ddjvu_page_set_rotation(page, (ddjvu_page_rotation_t)rotation4);

        while (ddjvu_job_status(ddjvu_page_job(page)) >= ddjvu_status_t.DDJVU_JOB_OK)
            SpinDdjvuMessageLoop(ctx, true);
        if (ddjvu_job_status(ddjvu_page_job(page)) >= ddjvu_status_t.DDJVU_JOB_FAILED)
        {
            base.OnPaint(e);
            return;
        }
        IntPtr fmt = ddjvu_format_create(ddjvu_format_style_t.DDJVU_FORMAT_BGR24, 0, (UIntPtr)null);
        ddjvu_format_set_row_order(fmt, /* top_to_bottom */1);
        ddjvu_rect_t prect = new ddjvu_rect_t(full.X, full.Y, (uint)full.Width, (uint)full.Height);
        ddjvu_rect_t rrect = new ddjvu_rect_t(screen.X, 2 * full.Y + screen.Y + full.Height - screen.Height, (uint)screen.Width, (uint)screen.Height);


        int stride = ((screen.Width * 3 + 3) / 4) * 4;
        //byte tmp;
        ////ScopedMem<char> bmpData(SAZA(char, stride * (screen.dy + 5)));
        //for (int y = 0; y < rrect.h; y++) {
        //    int step_y = y * SCREEN_WIDTH;
        //    for (int x=0; x < rrect.w; x++) {
        //        tmp = (byte)((imagebuf[x + step_y] >> 5) << 5);
        //    }
        //}
        int rowsize = mediaboxes[0].Width * 3;
        int nSize = rowsize * (mediaboxes[0].Height) * 10;

        unsafe
        {
            byte* buffer = (byte *)Memory.Alloc(nSize);
            try
            {
                IntPtr ptr1 = (IntPtr)Memory.Alloc(Marshal.SizeOf(prect));
                Marshal.StructureToPtr(prect, ptr1, false);

                IntPtr ptr2 = (IntPtr)Memory.Alloc(Marshal.SizeOf(rrect));
                Marshal.StructureToPtr(rrect, ptr2, false);

                byte[] array = new byte[nSize];
                fixed (byte* p = array) Memory.Copy(buffer, p, nSize);
                ddjvu_page_render(page, ddjvu_render_mode_t.DDJVU_RENDER_MASKONLY, ptr1, ptr2, fmt, (ulong)stride, array);
            }
            finally
            {
                Memory.Free(buffer);
            }

ddjvu_page_render应返回要在给定矩形区域中呈现的页面的任意数据。之后,我应该能够从任意数据创建图像&amp;显示在屏幕上

1 个答案:

答案 0 :(得分:0)

以下是我将如何编写p / invoke:

[DllImport(dllname, CharSet=CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern int ddjvu_page_render(
    [In] IntPtr page, 
    [In] ddjvu_render_mode_t mode, 
    [In] ref ddjvu_rect_t pagerect,
    [In] ref ddjvu_rect_t renderrect,
    [In] ref ddjvu_format_t pixelformat,
    [In] uint rowsize,
    [Out] byte[] imagebuffer
);

请注意,我已停止使用unsafe,并让编组人员自动处理结构。

这里有一些我无法验证的假设:

  • 调用约定。它可能不是cdecl。 C ++标题将有明确的答案。
  • 第一个参数是void*句柄类型,我猜是。
  • ddjvu_render_mode_t是您已正确翻译的枚举。
  • 三个ref参数是结构,通过引用传递。我无法检查您是否正确翻译了它们。

调用此函数将是这样的:

byte[] imagebuffer = new byte[nSize];
int retval = ddjvu_page_render(
    page, 
    ddjvu_render_mode_t.DDJVU_RENDER_MASKONLY, 
    ref prect, 
    ref rrect, 
    ref fmt, 
    (uint)stride, 
    imagebuffer
);
if (retval != ??) 
    // handle error

这是一个非常广泛的答案。我希望它能指出你正确的方向。我不认为你的所有问题都会被解决。