NPAPI Module Plugin Error

I am trying to use NPAPI Framework from Yuri Sidorov, following this answer:

How to embed a Delphi VCL form in an HTML page using NPAPI

but I get an error with NPPlugin.pas. I am using delphi XE7 and this is what I did following the instructions of Crom Stern

procedure DefDebugOut(const Msg: string); begin OutputDebugStringA(PAnsiChar(Msg + #13#10)); // Changed From Pchar To PAnsiChar end; 

but still getting a compiler error with this message

[dcc32 error] NPPlugin.pas (2215): E2010 Incompatible types: 'PWideChar' and 'PAnsiChar'

Error executing this procedure.

 procedure TPlugin.SetException(const msg: string); var s: String; begin try {$ifopt D+} NPP_DebugOut('Exception: ' + msg); {$endif} s:=UTF8Encode(msg); NPN_SetException(m_pScriptableObject, PAnsiChar(s)); except { prevent any exception from leaking out of DLL } end; end; 

here is the NPN_SetException procedure

 procedure NPN_SetException(npobj: PNPObject; msg: PNPUTF8); begin NavigatorFuncs.SetException(npobj, msg); end; 
-1
source share
2 answers

This NPAPI code was explicitly designed for older versions of Delphi before migrating to Unicode in Delphi 2009. String / (P)Char types are no longer aliases for AnsiString / (P)AnsiChar , now they are aliases for UnicodeString / (P)WideChar . A UnicodeString cannot be sent to PAnsiChar , just as AnsiString never be sent to PWideChar .

In DefDebugOut() simplest solution is to change PAnsiChar to PChar and change OutputDebugStringA() to OutputDebugString() :

 procedure DefDebugOut(const Msg: string); begin OutputDebugString(PChar(Msg + #13#10)); end; 

This is compatible with all versions of Delphi (the code should have done this from the very beginning - there was no reason to call OutputDebugStringA() directly). PChar and OutputDebugString() displayed in PAnsiChar and OutputDebugStringA() in Delphi 2007 and earlier, and PWideChar and OutputDebugStringW() in Delphi 2009 and later. So, everything is consistent.

In TPlugin.SetException() , UTF8Encode() returns UTF8String in all versions of Delphi. However, until Delphi 2009, UTF8String was just an alias for AnsiString , but in Delphi 2009 it was changed to the true UTF-8 string type with full RTL support (it still has AnsiString base, so it can still be dropped to PAnsiChar ). When a UTF8String assigned to a UnicodeString , the compiler performs an implicit conversion of the data from UTF-8 to UTF-16. And, as stated above, a UnicodeString cannot be sent to PAnsiChar . Therefore, you need to change the s variable from String to UTF8String for all versions of Delphi:

 procedure TPlugin.SetException(const msg: string); var s: UTF8String; begin try {$ifopt D+} NPP_DebugOut('Exception: ' + msg); {$endif} s:=UTF8Encode(msg); { UTF8Encode() is deprecated in Delphi 2009+. In those versions, you can use this instead: s := UTF8String(msg); } NPN_SetException(m_pScriptableObject, PAnsiChar(s)); except { prevent any exception from leaking out of DLL } end; end; 

With that said, if you still get the same error when calling NPN_SetException() , then this means that the second parameter NPN_SetException() declared as PChar . It should be declared as PAnsiChar .

+1
source

I will start with a breakdown of what we can see. Keep in mind that we do not have NPPlugin.pas at hand and you need to infer its contents from the information in the question. However, I think it is possible for us to do this for sure.


 s := UTF8Encode(msg); 

Here s is of type string . This is an alias for UnicodeString encoded as UTF-16. This way you convert from UTF-16 to UTF-8, and then back to UTF16.

You need it like this:

 NPN_SetException(m_pScriptableObject, PAnsiChar(UTF8Encode(msg))); 

Alternatively, if you need a variable to store UTF-8 encoded text, declare it UTF8String , which is equal to AnsiString(65001) . If you changed type s to UTF8String , then the code in the question will be correct. Although somewhat more detailed than it should be.


Another problem here:

 OutputDebugStringA(PAnsiChar(Msg + #13#10)); 

Your order does not make Msg actually 8-bit encoding. However, you do not want to use the version of the ANSI function. You need it:

 OutputDebugString(PChar(Msg + sLineBreak)); 

Your exception handler is wrong. The task of a DLL is not to rule out leaks. If you try to catch and suppress them, you simply mask the errors in your own code. You need to remove the exception handler and check for errors by following the instructions provided by the library documentation.


Now to the big picture. None of the above explains your reported error. The only sound explanation for this is that your declaration for NPN_SetException accepts wide text. In this case, you can compile the code simply by writing this:

 NPN_SetException(m_pScriptableObject, PChar(msg)); 

Of course, this makes the appearance of UTF-8 somewhat inexplicable. In fact, the Mozilla library accepts 8-bit text encoded by UTF-8. So, why did NPN_SetException expect UTF-16 text to be accepted? Well, that is not so. The explanation is that you incorrectly declared NPN_SetException . So, just to be clear, and PChar(msg) will make your code compile, this will not solve your problem. You still have code that was not executed at runtime.

So how did this happen? You took the working part of the code that used PChar aliased to PAnsiChar on Delphi with PChar with the alias PWideChar and not translated correctly. Even when you get the code to compile, it will not work correctly. You started with the code as follows:

 function NPN_SetException(..., Msg: PChar): ...; 

In older versions of Delphi, where PChar was PAnsiChar , that was correct. You are compiling it now on XE7, where PChar is PWideChar , and therefore this is not true. It should be:

 function NPN_SetException(..., Msg: PAnsiChar): ...; 

Then the calling code could be:

 NPN_SetException(m_pScriptableObject, PAnsiChar(UTF8Encode(msg))); 

My advice is that you:

  • Go back and go to Unicode processing in Delphi.
  • Go back to the source code and change the Mozilla interface code that uses PChar to PAnsiChar .
  • Whenever you need to let PAnsiChar do this with PAnsiChar(UTF8Encode(str)) .
+2
source

Source: https://habr.com/ru/post/911790/


All Articles