ズズズなブログ

はてブロ出戻り組です〜

Windows11: Google日本語入力で辞書に単語を登録する(その2)

以前こんな記事を書いたけど、もっと楽な方法があったのでメモる。

プロパティダイアログを表示させるコマンドのショートカットを作って、それを起動する方法。

qiita.com

以下にショートカットの作り方を簡単にまとめる。

  1. デスクトップを右クリック > 新規作成 > ショートカット
  2. パスに下記1行をコピペ
    "C:\Program Files (x86)\Google\Google Japanese Input\GoogleIMEJaTool.exe" "--mode=config_dialog"
  3. ショートカットの名前はデフォでもいいけど、単純にGoogleIMEPropがいいと思う
  4. OKボタンを押すと、デスクトップに青色の「あ」と書かれたショートカットアイコンができる

あとは、それをダブルクリックすればGoogle日本語入力のプロパティが開ける。

元ネタのようにショートカットキーを設定するのもいいけどどうせ忘れるし、ショートカットの名前がGoogleIMEPropなら一度ダブルクリックで起動した後はスタートメニューで google まで入力すれば補完候補として表示されるからそれでいい。

めっちゃ楽になった。感謝!

nVIDIAのオーバーレイ表示を無効化する

Windows PCのグラボをRTX4060に替えて、ドライバ更新したらGeForce Experienceという(Steamをパクったような画面の)アプリが入った。

常駐してゲームごとにグラボを最適化してくれる賢そうなやつなんだけど、オーバーレイ表示とそれ用のショートカットキーがおせっかい機能として実装されている。

こいつが悪さして、Altキーのショートカットが諸々吸われてしまうので無効にする。

  1. スタートメニューに「ge」と入れて GeForce Experience を起動
  2. アプリの右上あたりにある歯車アイコンをクリック
  3. 全般 > ゲーム内のオーバーレイ をOFF

これで安息が訪れた。

 

cf.

[Alt + Z]で GeForce Experience が表示されてしまう – Born Digital サポート

 

 

Windows11: Google日本語入力で辞書に単語を登録する

追記
もっといい方法があったので、こっち↓をやったほうがいい。
zzz-kbd.hateblo.jp



Explorer Patcher を使ってるせいか、タスクトレイのGoogle日本語入力アイコンのプロパティダイアログを開けず、そこから直に単語登録できない。

かなり面倒だが、単語登録するには以下の手順でやる。

  1. 設定 > 時刻と言語 > 入力 > キーボードの詳細設定
  2. 「使用可能な場合にデスクトップ言語バーを使用する」をチェック
  3. 言語バーが表示される。ここで一旦タスクバーを左クリックする。
    (これやらないと言語バーのスパナアイコンを左クリックしても反応しないことあり)
  4. 言語バーのスパナアイコンを左クリック
  5. 「辞書ツール」か「単語登録」を選択
  6. 単語を登録
  7. 設定ダイアログに戻り、「使用可能な場合にデスクトップ言語バーを使用する」のチェックを外す

ていうか、なんぼなんでもめんどすぎ。

Googleスプレッドシートでeval()

jsのeval()関数をGoogleスプレッドシートでも使える。

でもスプレッドシート関数じゃないので、セルに直接=eval(A1)とか入れても「不明な関数」になるから、以下のようにGASで一旦ラップしてやる。

function my_eval(formula) {
  return eval(formula);
}

これで

  • A1セルに5 + (-3)
  • A2セルに=my_eval(A1)

と入力すると、A2セルに2が入るはず。

でまあ、eval()なのでセキュリティ的に危ないらしいが、Googleスプレッドシートで使ったときの具体的なリスクシナリオがちょっと思い浮かばない。
クラウドでどんなインジェクションされようが問題ない気がするんだけど、他の非公開のシートを公開されたりできるなら確かにヤバいな。でもまeval使ったシート自体が非公開なら改変されないから直接使うぶんには問題ないはず。

GoogleスプレッドシートにはExcelの「本当に開いてもいいですか?」的なのがないから危ないっちゃ危ないけど、内輪で使う分には問題ないよね。

ローカル編集可能なシートがヤバいとかかな。
だとすると、Googleスプレッドシートからキーボード履歴を取得して送信するトロイをインストールとかできるんだろうか。
そんなんされたらかなりやばそうだが。

うーん、セキュリティは難しいな。

Arduino:Serial.println()をC言語のソースから使いたい

サンプル書いたけど、ここにソース埋め込むのがめんどいのでGistを貼る。

arduino example: calling Serial.println() from a C source file · GitHub

C言語C++のクラスとか理解不能なので、一旦C++でラッパー関数を書いて、それを呼ぶようにする。

でも、なぜにC言語から使いたいのか?
たとえば、使いたいライブラリがCだからとか、C++にないC言語固有の機能を使いたいとか、まあいろいろあるよね。

ちなみに、C言語からではなくC++のソースからSerial.println()したいときはこんな2段構えのラップ不要で、.cppに

#include <Arduino.h>

するだけで使えるので、もしC++コンパイルが通るならソースを.cppにしてしまったほうが楽。

arduino example: calling Serial.println() from a C++ source file · GitHub


元ネタはこちら
stackoverflow.com

C++:extern "C" の基本

たまに使うと忘れてて毎回ググるハメになるので、自分用のメモとして残す。

C++のソースからCの関数を呼ぶとき

ざっくり説明
  • extern "C" は呼ぶ側の.cppファイルに書く
  • extern "C" は「この.cppファイルのにあるこの関数名はマングリングされていない」という意味になる
  • 素のexternがそうであるようにextern "C" も関数定義につけるのではなく、プロトタイプ宣言の前につけるのが基本
  • ArduinoのinoファイルからCの関数をコールする時もC++と同様に.inoファイル内で、コールしたいC関数のプロトタイプ宣言の前にextern "C" をつける
使用例
// sub.c    呼はれる側

// ここにextern宣言は不要だが、書いてもコンパイル・リンクは通る
// extern int x2(int n);

int x2(int n)
{
    return n * 2;
}
// main.cpp     呼ぶ側

#include <iostream>
using namespace std;

extern "C" int x2(int n);   // 関数をコールする側にextern "C"宣言を書く

int main()
{
    int x = 100;
    cout << x2(x) << endl;

    return 0;
}
# Makefile

.PHONY: clean
clean:
	rm -f *.o call-c

all: call-c

call-c: main.o sub.o
	g++ main.o sub.o -o call-c

main.o: main.cpp
	g++ -c main.cpp -o main.o

sub.o: sub.c
	gcc -c sub.c -o sub.o

makeして実行

$ make all && ./call-c
g++ -c main.cpp -o main.o
gcc -c sub.c -o sub.o
g++ main.o sub.o -o call-c
200

.oファイルのシンボル確認

$ nm sub.o main.o

sub.o:
0000000000000000 T x2                            <-- マングリングされていない

main.o:
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
000000000000009d t _GLOBAL__sub_I_main
0000000000000000 T main
                 U x2                            <-- マングリングされていない
0000000000000047 t _Z41__static_initialization_and_destruction_0ii
                 U _ZNSolsEi
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 b _ZStL8__ioinit||<

CのソースからC++の関数を呼ぶとき

ざっくり説明
  • extern "C" は呼ばれる側の.cppファイルに書く
  • extern "C" は「この.cppファイルのにあるこの関数名をマングリングするな」という意味になる
  • プロトタイプ宣言は呼ばれる側の.cppファイルには本来不要だが、C++コンパイラにマングリング不要の指示として.cppファイルに書く
  • 素のexternがそうであるようにextern "C" も関数定義につけるのではなく、プロトタイプ宣言の前につけるのが基本
  • 呼ぶ側の.cファイルには素のexternが必要
  • Arduinoのビルトイン関数やライブラリを.cファイル内からコールする時も同様に、.cファイル内でコールしたいArduino関数のプロトタイプ宣言の前に素のexternをつける(ただ、Arduinoの場合は、最終的に.inoからそれを呼ぶ必要があるので、ならば.cではなくいっそ.cppにするほうが楽)
使用例
// sub.cpp  呼ばれる側

extern "C" int x2(int n);   // x2()はこのファイル内からコールされないのでここにextern宣言は不要だが、
//                          // C++コンパイラにマングリング不要の指示として必須

int x2(int n)
{
    return n * 2;
}
// main.c   呼ぶ側

#include <stdio.h>

extern int x2(int n);   // 素のextern宣言を書く(そもそもCコンパイラにextern "C"はない)

int main(void)
{
    int x = 500;
    printf("%d\n", x2(x));

    return 0;
}
# Makefile

.PHONY: clean
clean:
	rm -f *.o call-cpp

all: call-cpp

call-cpp: main.o sub.o
	g++ main.o sub.o -o call-cpp

main.o: main.c
	gcc -c main.c -o main.o

sub.o: sub.cpp
	g++ -c sub.cpp -o sub.o

makeして実行

$ make all && ./call-cpp
gcc -c main.c -o main.o
g++ -c sub.cpp -o sub.o
g++ main.o sub.o -o call-cpp
1000

.oファイルのシンボル確認

nm sub.o main.o

sub.o:
0000000000000000 T x2            <-- マングリングされていない

main.o:
0000000000000000 T main
                 U printf
                 U x2            <-- マングリングされていない

要点

  • extern はC/C++共通で使えるが、extern "C" はC++コンパイラにしか理解できない(言い換えると.cppにしかextern "C"を書けない)
  • extern "C" は呼ぶ側/呼ばれる側のどちらに書くかで意味が異なる
    • 呼ぶ側:「外部にあるこの関数名はマングリングされていない」という情報を与える
    • 呼ばれる側:「この関数名をマングリングするな」という指示を与える

補足

CソースからC++関数を呼ぶときは下記のように関数定義全体をextern "C" {}で囲んでもよい。

// sub.cpp  呼ばれる側

extern "C" {

int x2(int n)
{
    return n * 2;
}

}

C/C++コンパイラのどちらからも使われる可能性のあるヘッダファイルの場合は下記のように始まりと終わりをそれぞれ#ifdefと#endifで囲む必要がある。

// sub.h  C/C++共通のヘッダファイル

#ifdef __cplusplus
extern "C" {
#endif

// プロトタイプ宣言
int foo();
void bar(int x);

#ifdef __cplusplus
}
#endif