PDFiumSharp icon indicating copy to clipboard operation
PDFiumSharp copied to clipboard

How to pass structs to the C# interop layer?

Open wolf81 opened this issue 1 year ago • 0 comments

I'm trying to achieve the following:

  • Get all text objects in a page
  • Replace each text object for a new text object with same text but using a default font.

Code looks as follows:

public void UpdateFonts()
{
    FPDF_FONT font = PDFium.FPDFText_LoadStandardFont(Handle, "Helvetica");

    for (var i = 0; i < GetPageCount(); i++)
    {
        FPDF_PAGE pageHandle = Pages[i].Handle;
        FPDF_TEXTPAGE textPageHandle = PDFium.FPDFText_LoadPage(pageHandle);

        var pageObjCount = PDFium.FPDFPage_CountObjects(pageHandle);

        for (var j = pageObjCount - 1; j > 0; j--)
        {
            FPDF_PAGEOBJECT pageObj = PDFium.FPDFPage_GetObject(pageHandle, i);
            PageObjTypes pageObjType = PDFium.FPDFPageObj_GetType(pageObj);

            if (pageObjType == PageObjTypes.Text)
            {
                FPDF_PAGEOBJECT textObj = PDFium.FPDFPageObj_CreateTextObj(Handle, font, 10);

                byte ptr = 0;

                ulong length = PDFium.FPDFTextObj_GetText(textObj, textPageHandle, ref ptr, 0);

                if (length > 0)
                {
                    byte[] buffer = new byte[length];
                    var text = Encoding.Unicode.GetString(buffer, 0, (int)length - 2);
                    PDFium.FPDFText_SetText(textObj, text);
                }

                var matrix = new FS_MATRIX();
                if (PDFium.FPDFPageObj_GetMatrix(pageObj, matrix))
                {
                    PDFium.FPDFPage_RemoveObject(pageHandle, pageObj);
                    PDFium.FPDFPageObj_SetMatrix(textObj, matrix);
                }
            }
        }
    }
}

Now the issue I encounter is when I try to set the matrix based on matrix from the old text object (FPDFPageObj_SetMatrix). An error occurs:

PDFiumSharp.Tests.PdfDocumentTests.CloneDocument  Source: PdfDocumentTests.cs line 41  Duration: 123 ms

Message:  System.Runtime.InteropServices.MarshalDirectiveException : Cannot marshal 'parameter #2': Invalid managed/unmanaged type combination (this value type must be paired with Struct).

Stack Trace:  PlatformInvoke.FPDFPageObj_SetMatrix_Winx64(FPDF_PAGEOBJECT path, FS_MATRIX matrix) PDFium.FPDFPageObj_SetMatrix(FPDF_PAGEOBJECT path, FS_MATRIX matrix) line 8163 PdfDocument.UpdateFonts() line 245 PdfDocumentTests.CloneDocument() line 47 RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

How can I pass this matrix to the C# interop layer? This issue is the same with other structs by the way, based on my experience.

wolf81 avatar Jul 22 '24 03:07 wolf81