-1

UPDATE 3-4-15:11IS As recommended by David modified PInvoke as below, this time I am getting different error "Unhandled exception of type System.ExecutionEngineException occurred in mscorlib.dll"

    [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);

Thanks David for your valuable time, I think is close to a fix.

HISTORY

I know there are many questions in this subject but none of them help to resolve the issue I am currently facing.

Below is the API function in C Language

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 );

Below is the PInvoke signature of C Function added in .NET code

[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);

Below is how I am calling this function in the c# code

            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);
            }

call to ddjvu_page_render in above code is throwing "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." Prior to this post I must have tried all the option could find in various blogs. Appreciate any help, is almost a day I am clueless, your timely help could save my job

UPDATE 3-4-15:7:44IS This code is using DJVULibre

UPDATE 3-4-15:8:35IS

Here is the code I have in 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);
    }

In OnPaint function I have this below code

        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 should return arbitrary data of page which is to be rendered in a given rectangle area. Once after that I should be able to create image from arbitrary data & display in the screen

Naga
  • 2,368
  • 3
  • 23
  • 33
  • Impossible to answer. We've no idea what's on the other side of the interop. No need for unsafe either. Sure your current code won't compile without it, but you don't need to write it that way. – David Heffernan Mar 04 '15 at 14:01
  • David, the code is compiled successfully at runtime throwing error while calling ddjvu_page_render function. This .NET code is using DJVULibre C++ library – Naga Mar 04 '15 at 14:14
  • Like I said, it's impossible to answer when we can only see one side of the interop. Please don't expect us to do lots of research. Present clearly both sides of the interop, with all information that we need to be able to critique your interop. – David Heffernan Mar 04 '15 at 14:24
  • Dear David, appreciate your time & attention. First I am using P/Invoke not interop to call C++ methods. This code is using DJVULibre which is a 3-rd party c++ library used for compression. While invoking DJVU function(ddjvu_page_render) from C# code getting this error message. I know this is an issue with memory management, something to correct in pinvoke signature – Naga Mar 04 '15 at 14:55
  • We appear to be trapped in a non-terminating loop. I fully understand the nature of your problem. What I am telling you is that it cannot be solved if we only have half of the information. The missing half is the details of the unmanaged interface. When I look at the question I can only see managed code. – David Heffernan Mar 04 '15 at 14:56
  • Thanks for your time David, missing half is in this link http://www.djvu-soft.narod.ru/ddjvuapi.htm you can search for ddjvu_page_render in this page – Naga Mar 04 '15 at 14:59
  • It's no good in an offsite link that we need to trawl through. The onus is on you to spend the time to pick out the pertinent details and present a narrow and focused question. Please make sure you do more than present a raw code dump. Cut it down to just what we need. And make sure that we know how to call the function, not just the type of its parameters. – David Heffernan Mar 04 '15 at 15:00
  • Thanks again David. Here is the cut down 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 ); – Naga Mar 04 '15 at 15:02
  • It needs to be in the question. It's unreadable there. Please also read my comments again and take heed of all of my points. We have no idea how to pass to those parameters. One clear mistake is that `long` is 64 bits in C#. In C++ on Windows `long` is 32 bits. – David Heffernan Mar 04 '15 at 15:04
  • Thanks again David, I have now updated the question with all the code flow, hope is informative now – Naga Mar 04 '15 at 15:15
  • I still cannot see the information I asked for. At this point I concede defeat. Beyond the `long` error, your use of `unsafe` makes like hard, and your use of `IntPtr` for the structs also makes it difficult for you. The structs should be `ref StructType structValue`. Anyway, I've given enough time here already. Sorry. – David Heffernan Mar 04 '15 at 15:22
  • Thanks again David, apologize for tough time, I now updated the question. Shall try with your suggestions – Naga Mar 04 '15 at 17:10
  • Thanks for your edits. I've tried to help with a sketched answer. – David Heffernan Mar 04 '15 at 18:30

1 Answers1

0

Here's how I would write the 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
);

Note that I've stopped using unsafe, and am letting the marshaler handle the structs automatically.

There are quite a few assumptions here that I cannot verify:

  • The calling convention. It might not be cdecl. The C++ header will would have the definitive answer.
  • The first parameter is a void* handle type, I presume.
  • ddjvu_render_mode_t is an enum that you have translated correctly.
  • The three ref parameters are structs, passed by reference. I cannot check that you have translated them correctly.

Calling this function would be something like this:

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

This is quite a broad brush answer. I hope it points you in the right direction. I don't think that all your problems will be solved by this.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • David, I made changes exactly as you suggested except that for ddjvu_format_t for which could not locate its definition in c++ library reference, instead I still using the same IntPtr, from the debugging window I could see a valid pointer returned by ddjvu_format_create which is called prior to this function. The result is same, I am getting "Unhandled exception of type System.ExecutionEngineException occurred in mscorlib.dll". The calling convention is CDecl as I could confirm from ddjvuapi.h. Thanks again for your time & attention. – Naga Mar 05 '15 at 10:59
  • Then you've got a problem in your code. As I explained in my answer, there are still large parts of this that I cannot see. – David Heffernan Mar 05 '15 at 11:03