FF addon: Как да декларирам 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, използвайте опциите за кръстосана платформа, това е най-добре, но в името на обучението можем да направим това fget, когато имам малко време, ако не го разберете

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
Няма да го използвам в моя плъгин. Просто разработвам sth за себе си и искам да използвам 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

добре, имах малко време, така че си поиграх с него и имам нужда от вашата помощ да го поправя.

това е твоята версия, оправих я. копирайте, поставете това в scratchpad, задайте го на среда > браузър и го стартирайте

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 като 2-ри аргумент на ред 30
  • ред - е настроен на "ctypes.jschar("A")" без кавички, което е първият знак във файла, но казах get 2 char защо не даде първите 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