このページは、まだ未完成です。。。

nicotalk&キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html (2024年5月16日)

この記事を作った動機

 electron で何かアプリを作ろうかなと思ったとき、心理的障壁として、IPC によるやり取りがあったので、それについて、間違ってもいいのでとにかく自分なりにノートを作ろうと思っただけ。

IPC

なにそれおいしいの?

 IPC(Inter Process Communication) とは、複数のプログラム間で、データをやり取りしたりするための仕組みの一つ。いろんな仕組みがある。ネットワークを使うとか特定のメモリ領域を共有するとか。。。

electron と何が関係あるの?

 今の私の理解だと、electron は複数のプロセスからなっていて、単に一つのプログラムに対して、一つのプロセスが起動しているという感じではない。少なくとも、OS側の処理を担う、main と呼ばれているプロセスと、chromiumベースの描画用のプロセス(renderer.jsもここ)が存在している。

 セキュリティの関係上、一つのプロセスとして全てが処理されておらず、分離されている。そのため、例えばファイル操作を実装したいとなったときなどには、main プロセスと、renderer.js などが動いている描画用プロセス間でデータをやり取りする必要がある。

 そこで、データをやり取りする手段として、IPCがある。

やり方

 以下は適当に、Using Preload Scripts | Electronあたりから、IPCを使って main プロセスと描画プロセスがやり取りするために必要であると思われる部分を、部分的に引っ張っていじくりまわして試したコードである。

main.js

  • preload.js を指定
  • ipcMain.handle
const { app, BrowserWindow, ipcMain } = require('electron/main')
const path = require("node:path")

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
		preload: path.join(__dirname, 'preload.js')
	}
  })
  win.loadFile('src/index.html')
}

function scandir(){
	return ["aaa.txt","bbb.txt"]
}

app.whenReady().then(() => {
  	createWindow()

	ipcMain.handle("ping",() => "pong")
	ipcMain.handle("scandir",scandir)

	app.on('activate', () => {
		if (BrowserWindow.getAllWindows().length === 0) {
			createWindow()
		}
	})
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

preload.js

  • renderer.js内での呼び出し方の決定
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld("callme",{
  ping: () => ipcRenderer.invoke("ping"),
  scandir: () => ipcRenderer.invoke("scandir")
})
// renderer.js
// let response = await window.callme.ping()

 以下は、Using Preload Scripts | Electronの引用

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron,
  ping: () => ipcRenderer.invoke('ping')
  // we can also expose variables, not just functions
})

index.html

<!DOCTYPE html>
<html>
  ...
  <script src="./renderer.js"></script>
  ...
</html>

renderer.js

const func = async () => {
    const response = await window.callme.ping()
    alert(response)
    const res = await window.callme.scandir()
    console.log(res)
}

console.log("this is test")
func()

参考にしたサイトとか