Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Native Modules in Electron

Ana Betts
August 26, 2015

Native Modules in Electron

Talk given at Bay Area Electron User Group

Ana Betts

August 26, 2015
Tweet

More Decks by Ana Betts

Other Decks in Programming

Transcript

  1. Such as? • Showing Windows 10 No0fica0ons • Detec0ng the

    current keyboard layout and language • Doing language / script detec0on of text via cld2 • Spellchecking • Checking whether the OS is in presenta0on mode • Detec0ng whether we're in a Remote Desktop session
  2. Crea%ng a Na%ve Node Module • Write some C++ code

    that integrates with node.js, just like you would for server-side node.js • Go?a think about three different plaCorms • Debugging is Not A Joy, but at least you can try your module in node.js first • Always, always, always use nodejs/nan
  3. Crea%ng a Na%ve Node Module h"ps:/ /github.com/atom/node-spellchecker is the canonical

    Electron na:ve node.js module. It shows: • How to write OS-specific implementa5ons • Split your normal C++ code away from your Nan code and integrate it at the last minute • Write the bare minimum C++ code and use a JS shim to fill in the blanks (lib/spellchecker.js)
  4. Not All Nodes Are Created Equal • Electron typically ships

    a super-ass new version of io.js, and your system node.js probably isn't that, so anything you install via npm install is Borked • Even if they're the same, on Windows, you'll get module iniAalizaAon failures if you try to use an io.js module
  5. electron-rebuild, not so easy mode shouldRebuildNativeModules(pathToElectron) .then((shouldBuild) => { if

    (!shouldBuild) return true; return installNodeHeaders('v0.30.5') .then(() => rebuildNativeModules('v0.30.5', './node_modules')); }) .catch((e) => { console.error("Building modules didn't work!"); console.error(e); });
  6. node-ffi OSVERSIONINFO = OSVERSIONINFO || refStruct({ dwOSVersionInfoSize: ref.types.uint32, dwMajorVersion: ref.types.uint32,

    dwMinorVersion: ref.types.uint32, dwBuildNumber: ref.types.uint32, dwPlatformId: ref.types.uint32, szCSDVersion: refArray(ref.types.byte, 128), }); pLASTINPUTINFO = pLASTINPUTINFO || ref.refType(LASTINPUTINFO); pOSVERSIONINFO = pOSVERSIONINFO || ref.refType(OSVERSIONINFO); kernel32 = kernel32 || ffi.Library('kernel32', { 'GetVersionExA': [ 'int', [ pOSVERSIONINFO ] ], 'GetLastError': [ 'uint32', [] ] });
  7. node-ffi getOSVersion: () => { let result = new OSVERSIONINFO();

    result.dwOSVersionInfoSize = OSVERSIONINFO.size; let failed = (kernel32.GetVersionExA(result.ref()) === 0); if (failed) { let gle = kernel32.GetLastError(); throw new Error(`Failed to get version information: 0x${gle.toString(16)}`); } return { major: result.dwMajorVersion, minor: result.dwMinorVersion, build: result.dwBuildNumber, }; }
  8. edge.js import edge from 'edge-atom-shell' const helloWorld = edge.func(function ()

    {/* async (input) => { return "This is C# code: " + input.ToString(); } */}); helloWorld('JavaScript', (error, result) => { if (error) throw error; console.log(result); });
  9. edge.js public async Task<object> Invoke(object isWin10) { try { var

    notifier = (bool)isWin10 ? (INotifier)new Win10Notifier() : (INotifier)new Win7Notifier(); var ret = new Func<object, Task<object>>(async opts => { if (opts == null) { notifier.Dispose(); return null; } return await notifier.ShowNotification((string)opts); }); return ret; } catch (Exception ex) { return ex.ToString(); } }