Delphi NPAPI插件框架错误

Delphi NPAPI插件框架错误,delphi,npapi,delphi-xe7,browser-plugin,Delphi,Npapi,Delphi Xe7,Browser Plugin,我尝试使用Yury Sidorov的NPAPI框架,回答如下: 但是我在NPPlugin.pas中遇到了一个错误。我使用的是DelphiXe7,下面是我按照Krom Stern的说明所做的 procedure DefDebugOut(const Msg: string); begin OutputDebugStringA(PAnsiChar(Msg + #13#10)); // Changed From Pchar To PAnsiChar end; 但是编译器仍然会收到错误消息 [dc

我尝试使用Yury Sidorov的NPAPI框架,回答如下:

但是我在NPPlugin.pas中遇到了一个错误。我使用的是DelphiXe7,下面是我按照Krom Stern的说明所做的

procedure DefDebugOut(const Msg: string);
begin
  OutputDebugStringA(PAnsiChar(Msg + #13#10)); // Changed From Pchar To PAnsiChar
end;
但是编译器仍然会收到错误消息

[dcc32错误]NPPlugin.pas(2215):E2010不兼容类型:“PWideChar”和“PAnsiChar”

此过程中出现错误

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;
以下是程序NPN_SetException

procedure NPN_SetException(npobj: PNPObject; msg: PNPUTF8);
begin
  NavigatorFuncs.SetException(npobj, msg);
end;

我将从我们所能看到的逐件细分开始。请记住,我们手头没有
NPPlugin.pas
,必须从问题中的信息推断其内容。尽管如此,我认为我们有可能准确地做到这一点


这里的
s
类型为
string
。这是UnicodeString的别名,编码为UTF-16。因此,将UTF-16转换为UTF-8,然后再转换回UTF16

你需要像这样:

NPN_SetException(m_pScriptableObject, PAnsiChar(UTF8Encode(msg)));
或者,如果需要一个变量来保存UTF-8编码的文本,则将其声明为
UTF8String
,即
AnsiString(65001)
。如果将
s
的类型更改为
UTF8String
,则问题中的代码是正确的。虽然比需要的要详细一些


另一个问题是:

OutputDebugStringA(PAnsiChar(Msg + #13#10));
您的演员阵容不会使
Msg
实际上是8位编码的。但是,您不希望使用该函数的ANSI版本。你需要这个:

OutputDebugString(PChar(Msg + sLineBreak));

您的异常处理程序被误导了。DLL的任务是不泄漏异常。如果您试图捕获并抑制它们,那么您只需在自己的代码中屏蔽错误。您需要删除该异常处理程序,并按照库文档给出的说明检查错误


现在来看看大局。以上这些都不能解释您报告的错误。对此唯一合理的解释是,
NPN_SetException
的声明接受宽文本。在这种情况下,您只需编写以下代码即可编译代码:

NPN_SetException(m_pScriptableObject, PChar(msg));
当然,这使得UTF-8的外观有些令人费解。事实上,Mozilla库确实接受8位文本,UTF-8编码。那么,为什么
NPN\u SetException
希望传递UTF-16文本呢?但事实并非如此。原因是您错误地声明了
NPN_SetException
。因此,我要明确一点,虽然
PChar(msg)
会让您的代码编译,但它不会解决您的问题。您将留下在运行时失败的代码

那么,这是怎么发生的?您已将一段使用了别名为
PAnsiChar
PChar
的工作代码带到Delphi上,其别名为
PWideChar
,但未正确翻译。即使在编译代码时,它也无法正常工作。您从以下代码开始:

function NPN_SetException(..., Msg: PChar): ...;
在较早的Delphi版本中,
PChar
PAnsiChar
,那么这是正确的。您现在是在XE7上编译的,
PChar
PWideChar
,因此这是不正确的。它需要:

function NPN_SetException(..., Msg: PAnsiChar): ...;
那么调用代码可以是:

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

我的建议是:

  • 退一步,重新讨论Delphi中Unicode的处理
  • 返回原始代码,将所有使用
    PChar
    的Mozilla界面代码更改为
    PAnsiChar
  • 无论何时需要提供
    PAnsiChar
    都可以使用
    PAnsiChar(UTF8Encode(str))

    在Delphi 2009中切换到Unicode之前,此NPAPI代码显然是为旧版本的Delphi设计的。默认的
    String
    /
    (P)Char
    类型不再是
    AnsiString
    /
    (P)AnsiChar
    的别名,它们现在是
    UnicodeString
    /
    (P)WideChar
    的别名。
    UnicodeString
    不能转换成
    PAnsiChar
    ,就像
    AnsiString
    不能转换成
    PWideChar
    一样

    dedebugout()
    中,最简单的修复方法是将
    PAnsiChar
    更改为
    PChar
    ,并将
    outputdugstringa()
    更改为
    outputdugstring()

    这与所有Delphi版本兼容(代码从一开始就应该这样做-没有理由直接调用
    OutputDebugStringA()
    PChar
    OutputDebugString()
    映射到Delphi 2007和更早版本中的
    PAnsiChar
    OutputDebugStringA()
    ,以及Delphi 2009和更高版本中的
    PWideChar
    OutputDebugStringW()
    。所以一切都匹配

    TPlugin.SetException()
    中,
    UTF8Encode()
    在所有版本的Delphi中返回一个
    UTF8String
    。然而,在Delphi 2009之前,
    UTF8String
    只是
    AnsiString
    本身的别名,但在Delphi 2009中,它被更改为真正的UTF-8字符串类型,具有完全的RTL支持(它仍然具有
    AnsiString
    基础,因此它仍然可以转换为
    PAnsiChar
    )。当
    UTF8String
    被分配给
    UnicodeString
    时,编译器执行从UTF-8到UTF-16的隐式数据转换。如上所述,
    UnicodeString
    不能强制转换为
    PAnsiChar
    。因此,对于所有Delphi版本,您需要将
    s
    变量从
    String
    更改为
    UTF8String

    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;
    

    话虽如此,如果在
    NPN\u SetException()
    调用中仍然出现相同的错误,则表示
    NPN\u SetException()
    的第二个参数声明为
    PChar
    。它需要声明为
    PAnsiChar

    True,但这不能解释报告的编译器错误
    DefDebuggout
    编译,尽管它显然是错误的。编辑效果更好,但您仍然缺少根本问题。我的回答解释了什么
    procedure DefDebugOut(const Msg: string);
    begin
      OutputDebugString(PChar(Msg + #13#10));
    end;
    
    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;