首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >readStringReplaceMalformed()函数不能运行22以下的Mozilla版本?

readStringReplaceMalformed()函数不能运行22以下的Mozilla版本?
EN

Stack Overflow用户
提问于 2015-07-31 09:46:45
回答 1查看 108关注 0票数 1

我刚开始开发Mozilla-Firefox扩展。我正在为火狐创建一个附加的.xpi文件。直到今天都很好。但是,今天我安装了Firefox的一个版本,即Firefox-15.1并开始抛出以下异常:

在检查不同版本的Firefox时,我注意到这个外接程序在Firefox-22以下的版本上抛出了相同的异常。

有谁能告诉我为什么会这样。我是在代码中出错了,还是Firefox存在兼容性问题?如果是兼容性问题,请您给我提供任何参考文件。

下面是导致错误的示例代码:

MyJS.js :

代码语言:javascript
复制
var path="D:\\DemoExportFunction.dll";
Components.utils.import("resource://gre/modules/ctypes.jsm");						
var lib = ctypes.open(path);							
var getStr = lib.declare("getString",ctypes.default_abi,ctypes.char.ptr); 

function func_PageLoad(event) 
{   
   try  
   {
		alert("func_PageLoad");
		var str=getStr();
		str=str.readStringReplaceMalformed();
		alert("String:"+str);
		
  }
  catch(err)
  {
	alert("Exception in func_PageLoad Message : "+err.message);
  }
}

gBrowser.addEventListener("DOMContentLoaded", func_PageLoad, true);

.Dll代码:

代码语言:javascript
复制
#include "stdafx.h"
extern "C"
{
    __declspec( dllexport ) char * getString( );

}

char * getString( )
{
    return "Hello . . . . This is message from dll";
}
EN

回答 1

Stack Overflow用户

发布于 2015-07-31 21:29:40

您似乎在假设CData在火狐的整个生命周期中是静态的。然而,它当然是随着时间的推移而发展起来的(就像整个Firefox,或者几乎任何大型软件项目一样)。如果某个特定的函数在旧版本的Firefox中可用,则取决于该函数是何时实现并包含在Firefox中的。

至于文档,最终的文档是Firefox源代码。为了准确地定位这个函数最初在哪个版本中可用,我希望必须查看源代码并查看它何时添加。但是,您可以从其他方面获得一些提示,说明这是什么时候发生的。

它的文档被添加到2013年2月19日MDN上的CData页面中。自2010年8月9日以来没有对该页面进行任何修改。这显然是一个问题,在2012-05-17当Bug 756120 - CData readString的完全实现被提交.

MDN上的CData页面甚至包括了在readStringReplaceMalformed()不可用时有效使用的聚脂填充。该守则是:

代码语言:javascript
复制
function readAsChar8ThenAsChar16(stringPtr, known_len, jschar) {
    // when reading as jschar it assumes max length of 500

    // stringPtr is either char or jschar, if you know its jschar for sure, pass 2nd arg as true
    // if known_len is passed, then assumption is not made, at the known_len position in array we will see a null char
    // i tried getting known_len from stringPtr but its not possible, it has be known, i tried this:
        //"stringPtr.contents.toString()" "95"
        //"stringPtr.toString()" "ctypes.unsigned_char.ptr(ctypes.UInt64("0x7f73d5c87650"))"
        // so as we see neither of these is 77, this is for the example of "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox"

    // tries to do read string on stringPtr, if it fails then it falls to read as jschar

    var readJSCharString = function() {
        var assumption_max_len = known_len ? known_len : 500;
        var ptrAsArr = ctypes.cast(stringPtr, ctypes.unsigned_char.array(assumption_max_len).ptr).contents; // MUST cast to unsigned char (not ctypes.jschar, or ctypes.char) as otherwise i dont get foreign characters, as they are got as negative values, and i should read till i find a 0 which is null terminator which will have unsigned_char code of 0 // can test this by reading a string like this: "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox" at js array position 36 (so 37 if count from 1), we see 183, and at 77 we see char code of 0 IF casted to unsigned_char, if casted to char we see -73 at pos 36 but pos 77 still 0, if casted to jschar we see chineese characters in all spots expect spaces even null terminator is a chineese character
        console.info('ptrAsArr.length:', ptrAsArr.length);
        //console.log('debug-msg :: dataCasted:', dataCasted, uneval(dataCasted), dataCasted.toString());
        var charCode = [];
        var fromCharCode = []
        for (var i=0; i<ptrAsArr.length; i++) { //if known_len is correct, then will not hit null terminator so like in example of "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox" if you pass length of 77, then null term will not get hit by this loop as null term is at pos 77 and we go till `< known_len`
            var thisUnsignedCharCode = ptrAsArr.addressOfElement(i).contents;
            if (thisUnsignedCharCode == 0) {
                // reached null terminator, break
                console.log('reached null terminator, at pos: ', i);
                break;
            }
            charCode.push(thisUnsignedCharCode);
            fromCharCode.push(String.fromCharCode(thisUnsignedCharCode));
        }
        console.info('charCode:', charCode);
        console.info('fromCharCode:', fromCharCode);
        var char16_val = fromCharCode.join('');
        console.info('char16_val:', char16_val);
        return char16_val;
    }

    if (!jschar) {
        try {
            var char8_val = stringPtr.readString();
            console.info('stringPtr.readString():', char8_val);
            return char8_val;
        } catch (ex if ex.message.indexOf('malformed UTF-8 character sequence at offset ') == 0) {
            console.warn('ex of offset utf8 read error when trying to do readString so using alternative method, ex:', ex);
            return readJSCharString();
        }
    } else {
        return readJSCharString();
    }
}

这种类型的更改,添加了readStringReplaceMalformed()函数,对于此类接口的开发来说是正常的。这是您应该知道发生的事情,对API的这种更改/增强是您作为API的使用者应该知道的,以及它们对您的工作的影响。

Firefox的旧版本和兼容性:

在开发火狐扩展时,您应该完成的任务之一是选择您希望支持的最老版本的Firefox。您可以通过多种方法来实现这一点,但是您选择支持哪个最老版本限制了您可以在插件中使用的功能,或者要求您以两种或更多种不同的方式实现功能。例如,在Firefox 29上,如何从Firefox UI中插入/删除/更改项发生了相当大的变化。如果您正在对Firefox UI进行这样的更改(甚至只是添加一个按钮),那么在Firefox 29和Firefox 29之前以及以后,您的代码必须根据版本(或功能的可用性)选择使用不同版本的Firefox代码。对于最老的版本来说,具有这些基本和重大更改的版本通常是很好的选择,以支持您的附加版本。

最近我遇到了一个API更改的例子,当时回答另一个问题是一个用户,希望使用Element.closest()来简化他们的代码。但是,这样做的选择将限制代码只与Firefox 35.0或更高版本兼容。在编写与其他代码块(模块、API等)交互的代码时,这种类型的选择(使用新功能与旧版本保持兼容)将是您多次遇到的问题。

通常,您通常会根据以下各种因素来选择支持哪个最老版本的Firefox:

  1. 需要支持使用特定旧版本的客户。
  2. 所需功能的可用性(您的附加功能是否需要作为核心功能,只是在旧版本中无法使用,而无法解决/填充问题)。
  3. 使用旧版本安装的基础所占百分比
  4. 易于支持(即在不同版本之间更改了多少,您需要做哪些额外的编码来支持旧版本)。
  5. 您是否已经兼容(即在进行一些重大更改之前就已经存在了插件,并且必须编写与新版本兼容的代码(例如,在Firefox 29之前使用的火狐插件,并添加了与新UI API兼容的代码)。
  6. 许多其他因素

假设您没有需要支持旧版本或可以支持的最低版本的特定问题,那么您可能希望基于一个扩展支持发布(ESR)版本(例如24.0esr,31.0esr)来做出这个决定。

一般来说,您可能希望支持至少回到最近的ESR版本。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31743141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档