Аддон FF: как объявить функции C fgets в javascript

Я разрабатываю плагин Firefox и хочу прочитать файл с помощью WinApi. Мне удается подключиться к WinApi, и он отлично работает.

var lib = ctypes.open("user32.dll");
var msgBox = lib.declare("MessageBoxW",
                       ctypes.winapi_abi,
                       ctypes.int32_t,
                       ctypes.int32_t,
                       ctypes.jschar.ptr,
                       ctypes.jschar.ptr,
                       ctypes.int32_t);
var MB_OK = 0;
var ret = msgBox(0, "Hello world", "title", MB_OK);

Теперь я объявляю fopen:

const FILE = new ctypes.StructType("FILE").ptr;   
var fopen = libc.declare("fopen",                     // symbol name
                        ctypes.default_abi,           // cdecl calling convention
                        FILE,                         // return type (FILE*)
                        ctypes.char.ptr,              // first arg (const char*)
                        ctypes.char.ptr);             // second arg (const char*)

но я не могу объявить fgets. Я до сих пор не могу понять. Я пытаюсь сделать:

var libc = ctypes.open("msvcrt.dll");
var fgets = libc.declare("fgets",                    
                        ctypes.default_abi,           
                        ctypes.char.ptr,              
                        ctypes.char.ptr,              
                        ctypes.int32_t,               
                        FILE);                        
// Call the function, and get a FILE* pointer object back.
console.log(LOG_FILTER, "Try to open file.");
var file1 = fopen("1.in", "r");

  var SIZE = 100;
  var line = ctypes.char(SIZE).ptr;
  line = fgets(line, SIZE, file1);` 

Я думаю, что не использую неправильную библиотеку, потому что тогда я получаю сообщение об ошибке «Ошибка: не удалось найти символ функции в библиотеке», но я все равно получаю «TypeError: ожидаемый указатель типа, получен (void 0)»


person alicjab    schedule 21.02.2014    source источник
comment
Не отвечая на ваш конкретный вопрос. Но, пожалуйста, не используйте необработанные fopen и т. д., если этого можно избежать. Уже существует множество API доступа к файлам, таких как nsIFileInputStream или OS.File, которые не только являются кроссплатформенными и активно используются Firefox и другими -ons, но также проще в использовании и надежнее, чем возиться с js-ctypes.   -  person nmaier    schedule 22.02.2014
comment
Я знаю об этих API, но мне обязательно нужно использовать WinApi.   -  person alicjab    schedule 25.02.2014


Ответы (3)


вот пример набора различных объявлений ctype: https://builder.addons.mozilla.org/package/161408/latest/

если вы все еще не можете понять это, опубликуйте это, и я постараюсь заставить fget работать.

но делайте с namier рекомендуется, используйте кросс-платформенные варианты, это лучше всего, но ради обучения мы можем сделать это, когда у меня будет время, если вы не понимаете этого.

person Noitidart    schedule 22.02.2014
comment
Спасибо за ответ, пример полезен, но я все еще не могу сделать это правильно. Я отредактировал свой пост, чтобы показать, как я пытаюсь объявить fgets. Вы видите, что с ним не так? - person alicjab; 25.02.2014
comment
Изучу позже, но мне любопытно узнать о вашем fopen. const FILE = new ctypes.StructType("FILE").ptr; это указатель, вам не нужно определять структуру? Как это работает? это вообще работает? - person Noitidart; 26.02.2014
comment
Да, это работает. Когда я делаю var file = fopen("newfile.in", "w");, он создает новый файл. Const FILE используется только в объявлении функции, это не имеет значения. - person alicjab; 26.02.2014
comment
ок, посмотрю на это в ближайшее время, обязательно напомните мне, если я не получаю напоминания о вещах в свободное время, которые я склонен забывать. напоминайте мне, размещая здесь время от времени. я получаю уведомление - person Noitidart; 26.02.2014
comment
также вы действительно не реализуете это в своем аддоне, не так ли? вам действительно следует использовать osfile.jsm. я просто работаю над fget в учебных целях - person Noitidart; 26.02.2014
comment
Я не буду использовать его в своем плагине. Я просто разрабатываю что-то для себя и хочу использовать winApi вместо готовых API. - person alicjab; 26.02.2014
comment
Хорошо, мне наконец удалось прочитать файл. Я использовал getc вместо fgets . Спасибо за вашу помощь! - person alicjab; 26.02.2014
comment
не могли бы вы поделиться с нами getc, я действительно заинтересован в версии ctypes. я на самом деле изо всех сил пытаюсь сделать setWindowsHookEx в ctypes - person Noitidart; 26.02.2014

Итак, вот мое решение. Я решил использовать функцию getc вместо fgets, и мне удалось прочитать файл.

Components.utils.import("resource://gre/modules/ctypes.jsm");
var libc = ctypes.open("msvcrt.dll");

// int getc(FILE *stream);
var getc = libc.declare("getc",
                        ctypes.default_abi,
                        ctypes.int32_t,
                        FILE);
var file = fopen("newfile.in", "w");
var readFile = readFileToString(file)

function readFileToString(file) {
  var result = '';
  var c = 0;
  while((c = getc(file)) != -1) {
    result += String.fromCharCode(c); 
  }
  console.log("result = " + result);
  return result;
}
person alicjab    schedule 27.02.2014

Хорошо, у меня было немного времени, поэтому я поиграл с ним, и мне нужна ваша помощь, чтобы исправить это.

это твоя версия я исправил. скопируйте и вставьте это в блокнот, установите его в среду> браузер и запустите его.

Cu.import("resource://gre/modules/ctypes.jsm");
var libc = ctypes.open("msvcrt.dll");

var FILE = new ctypes.StructType("FILE").ptr; //made var otherwise in scratchpad cant run multiple times, this can be CONST its no issue
var fopen = libc.declare("fopen",                     // symbol name
                        ctypes.default_abi,           // cdecl calling convention
                        FILE,                         // return type (FILE*)
                        ctypes.char.ptr,              // first arg (const char*)
                        ctypes.char.ptr);             // second arg (const char*)


var fgets = libc.declare("fgets",                    
                        ctypes.default_abi,           
                        ctypes.char.ptr,              
                        ctypes.char.ptr,              
                        ctypes.int32_t,               
                        FILE);          


var myfile = fopen("C:\\Users\\3K2KYC1\\Desktop\\FirefoxPortable\\newfile.in", "r");

var SIZE = 100;
var line = new ctypes.char(SIZE);
var ret = fgets(line.address(), SIZE, myfile);   


Services.wm.getMostRecentWindow(null).alert(line);
Services.wm.getMostRecentWindow(null).alert(ret);

Результаты этого теста:

  • newfile.in уже существует и его содержимое "ABC" без кавычек
  • строка - после запуска строки кода устанавливается значение «ctypes.char (65)», а 65 - это код символа A, но как вы читаете строку?
  • ret - после запуска кода ret устанавливается в "ctypes.char.ptr(ctypes.UInt64("0x1e70e808"))" это также не имеет для меня смысла, как из этого получить строку?

Затем я кое-что изменил и сделал по-своему, но у меня похожие проблемы, я не могу прочитать более одного символа.

Cu.import("resource://gre/modules/ctypes.jsm");
var libc = ctypes.open("msvcrt.dll");


var struct_FILE = new ctypes.StructType("FILE"); //set to var only so can run multiple times in scratchpad, can change back to const
var fopen = libc.declare("fopen", // symbol name
    ctypes.default_abi, // cdecl calling convention
    struct_FILE.ptr, // return type (FILE*)
    ctypes.char.ptr, // first arg (const char*)
    ctypes.char.ptr); // second arg (const char*)

var fgetc = libc.declare("fgetc", // symbol name
    ctypes.default_abi, // cdecl calling convention
    ctypes.int.ptr, // return type (FILE*)
    struct_FILE.ptr); // second arg (const char*)

var fgets = libc.declare("fgets", // symbol name
    ctypes.default_abi, // cdecl calling convention
    ctypes.jschar.ptr, // return char pointer
    ctypes.jschar.ptr, // first arg char pointer
    ctypes.int, //second arg int
    struct_FILE.ptr); // third arg FILE pointer

var myfile = fopen("C:\\Users\\3K2KYC1\\Desktop\\FirefoxPortable\\newfile.in", "r");
//Services.wm.getMostRecentWindow(null).alert(myfile);



var line = new ctypes.jschar;
var ret = fgets(line.address(), 2, myfile);

Services.wm.getMostRecentWindow(null).alert(line);
Services.wm.getMostRecentWindow(null).alert(ret);
  • newfile.in уже существует и его содержимое "ABC" без кавычек
  • используя размер 2 в качестве второго аргумента в строке 30
  • строка - установлена ​​​​на "ctypes.jschar ("A")" без кавычек, что является первым символом в файле, но я сказал получить 2 символа, почему он не дал первые 2 символа, если попытка 3 дает что-то странное
  • ret - установлен в "ctypes.jschar.ptr(ctypes.UInt64("0xfba2b32"))"

  • если использовать размер 3

  • строка - "ctypes.jschar("䉁")"
  • ret - "ctypes.jschar.ptr(ctypes.UInt64("0x8fefce8"))"
person Noitidart    schedule 27.02.2014
comment
обязательно поделитесь со мной своей функцией getc, мне нужно посмотреть, как вы там все сделали - person Noitidart; 27.02.2014