PDFiumSharp
PDFiumSharp copied to clipboard
How to pass structs to the C# interop layer?
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.