JavaScriptで周期的処理

JavaScriptで周期的処理を行うサンプルです。関数setIntervalは、指定した関数を一定時間(単位はmsec)ごとに繰り返し実行する関数です。また、関数countupでは、関数のプロパティ(この例では、countup.i)がstatic変数のように振舞うことを利用しています。
JavaFXよりも簡潔に記述できるのが嬉しいです!

setInterval.htm

<html>
<head>

function countup() {
  if (typeof countup.i === 'undefined') {
    countup.i = 0;
  }
  document.getElementById('textField').value = countup.i++;
}

</head>
<body>

setInterval('countup()', 1000);

<input type='text' id='textField'>
</body>
</html>


参考サイト
1.JavaScriptでPHP関数におけるstatic変数みたいな事をやる

広告

JavaFXで周期的処理

今回紹介するのは、時間駆動プログラミングです。Timelineクラスを使えば JavaFX で周期的処理を行ったり、アニメーションを作成することができます。行いたい処理は、handle関数の中に記述します。今回の例では、コンストラクタの中で Timeline を使っていますが、コールバック関数の中で使うこともできます。

GUIアプリケーションの開発は、前回紹介したイベント駆動プログラミング(event-driven programming)と、周期的タスク(periodic task)やスケジュールされたタスク(scheduled task)を記述する時間駆動プログラミング(time-driven programming)を組み合わせて行うこともできます。

D:\JavaFX\abc1\abc2\abc3\Main.java

package abc1.abc2.abc3;

import javafx.application.*;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.stage.*;

public class Main extends Application {
  public void start(Stage stage) throws Exception {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("view.fxml"));
    stage.setScene(new Scene(fxmlLoader.load()));
    stage.show();
  }
}

D:\JavaFX\abc1\abc2\abc3\Controller.java

package abc1.abc2.abc3;

import javafx.animation.*;
import javafx.event.*;
import javafx.fxml.*;
import javafx.scene.control.*;
import javafx.util.*;

public class Controller {
  private int i;
  @FXML private Label label;
  public Controller() {
    Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1),
      new EventHandler<ActionEvent>() {
        public void handle(ActionEvent actionEvent) {
          label.setText(String.valueOf(i++));
        }
      }
    ));
    timeline.setCycleCount(Timeline.INDEFINITE);
    timeline.play();
  }
}

D:\JavaFX\abc1\abc2\abc3\view.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox prefHeight="100" prefWidth="200" fx:controller="abc1.abc2.abc3.Controller" xmlns:fx="http://javafx.com/fxml">
  <Label fx:id="label"/>
</VBox>


参考サイト

1.JavaFX 8でタイマー(処理の周期実行)を実装する

JavaFXの入門サンプル

JavaFX 初心者が作成した入門サンプルです。参考にしてくれると喜びます ^^
今回のプログラムは、イベント駆動プログラミングのサンプルです。次回は、時間駆動プログラミングを紹介します。


1.JavaFXプログラムの作成

プログラムは、Main.java、Controller.java、view.fxml から構成されます。view.fxml でGUI部品のレイアウトを規定し、Controller.java でイベント発生時の制御を行います。
下記のプログラムでは、関数 setText がイベント発生時(ボタンがクリックされた時)に呼び出される関数(コールバック関数)です。

D:\JavaFX\abc1\abc2\abc3\Main.java

package abc1.abc2.abc3;

import javafx.application.*;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.stage.*;

public class Main extends Application {
  public void start(Stage stage) throws Exception {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("view.fxml"));
    stage.setScene(new Scene(fxmlLoader.load()));
    stage.show();
  }
}

D:\JavaFX\abc1\abc2\abc3\Controller.java

package abc1.abc2.abc3;

import javafx.fxml.*;
import javafx.scene.control.*;

public class Controller {
  @FXML private TextField textField;
  @FXML private Label label;
  @FXML private void setText() {
    label.setText(textField.getText());
  }
}

D:\JavaFX\abc1\abc2\abc3\view.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox prefHeight="100" prefWidth="200" fx:controller="abc1.abc2.abc3.Controller" xmlns:fx="http://javafx.com/fxml">
  <Button text="Click" onAction="#setText"/>
  <TextField fx:id="textField"/>
  <Label fx:id="label"/>
</VBox>


2.コンパイル

javac0.bat を実行するとクラスファイルが生成されます。

D:\JavaFX\javac0.bat(ファイル名をjavac.batにすると暴走します)

set path=D:\sdk\jdk\bin
javac abc1/abc2/abc3/*.java


3.実行可能JARファイルの作成

マニフェストファイル manifest.mf を作成してから jar0.bat を実行すると、ダブルクリックするだけで実行できるJARファイル javafx.jar が生成されます。

D:\JavaFX\manifest.mf

Main-Class: abc1.abc2.abc3.Main

注意)Main-Class:の後の空白とabc1.abc2.abc3.Mainの後の改行を忘れると正常に動作しません。

D:\JavaFX\jar0.bat(ファイル名をjar.batにすると暴走します)

set path=D:\sdk\jdk\bin
jar cvfm javafx.jar manifest.mf abc1/abc2/abc3/*.class abc1/abc2/abc3/view.fxml


4.実行

実行可能JARファイル javafx.jar をダブルクリックするか、下記の java0.bat を実行してください。尚、ダブルクリックでプログラムを起動できるようにするには、予め JRE(Java Runtime Environment)をインストールしておく必要があります。

D:\JavaFX\java0.bat(ファイル名をjava.batにすると暴走します)

set path=D:\sdk\jdk\bin
java -jar javafx.jar


参考サイト

1.JavaFX 8 Tutorial
2.JARファイルの作成
3.ダブルクリックで実行できるJAR
4.Linux環境でのJARファイルの実行

MinGWによる共有ライブラリの作成と動的リンク

MinGW g++ を使った共有ライブラリ(DLL)の作成方法と動的リンクについて紹介します。動的リンクとは、実行時に実行ファイルとライブラリをリンクすることです。また、動的リンクには明示的リンクと暗黙的リンクがあり、DLLの明示的リンクではDLLを呼び出す関数の中でDLLのファイル名を明示しますが、暗黙的リンクでは明示しません。


共有ライブラリ(DLL)の作成

まず、下記のexample.cppを作成します。

example.cpp

extern "C" int add(int x, int y) {
  return x + y;
}

extern "C" int mul(int x, int y) {
  return x * y;
}

example.cppがあるフォルダでバッチファイルdll.batを実行すると、DLLが生成されます。

dll.bat

set path=D:\MinGW\bin
g++ -shared example.cpp -o example.dll
strip example.dll


実行ファイル(EXE)の作成(明示的リンクの場合)

明示的リンク用のプログラムexplicit.cppを作成します。このプログラムには、DLLのファイル名example.dllが明示されています。

explicit.cpp

#include <stdio.h>
#include <windows.h>

typedef int (*Add)(int, int);
typedef int (*Mul)(int, int);

int main() {
  HMODULE hModule = LoadLibrary("example.dll");
  Add add = (Add)GetProcAddress(hModule, "add");
  Mul mul = (Mul)GetProcAddress(hModule, "mul");
  printf("%d\n", add(1, 1));
  printf("%d\n", mul(1, 1));
  FreeLibrary(hModule);
  return 0;
}

explicit.cppがあるフォルダでバッチファイルexplicit.batを実行すると、実行ファイルcaller.exeが生成されます。

explicit.bat

set path=D:\MinGW\bin
g++ explicit.cpp -o caller.exe
strip caller.exe


実行ファイル(EXE)の作成(暗黙的リンクの場合)

暗黙的リンク用のプログラムimplicit.cppを作成します。このプログラムには、DLLのファイル名example.dllは明示されていません。

implicit.cpp

#include <stdio.h>

extern "C" int add(int, int);
extern "C" int mul(int, int);

int main() {
  printf("%d\n", add(1, 1));
  printf("%d\n", mul(1, 1));
  return 0;
}

implicit.cppとexample.dllがあるフォルダでバッチファイルimplicit.batを実行すると、実行ファイルcaller.exeが生成されます。コマンドラインオプション-lexampleのexampleはexample.dllのことです。
今回の方法では、LIBファイル(インポートライブラリ)を使っていません。その代わりにDLLファイルを使っています。
明示的リンクに比べ暗黙的リンクの方がプログラムを簡潔に記述できるので、通常は暗黙的リンクが用いられます。

implicit.bat

set path=D:\MinGW\bin
g++ implicit.cpp -L. -lexample -o caller.exe
strip caller.exe


EXEの実行

example.dllをパスが通っているフォルダかcaller.exeがあるフォルダに入れ、caller.exeがあるフォルダでバッチファイルrun.batを実行して下さい。尚、実行時にlibgcc_s_dw2-1.dllが必要になるので、D:\MinGW\binにパスを通しています。

run.bat

set path=D:\MinGW\bin
caller.exe
pause


参考サイト

1.ダイナミック リンク ライブラリ(DLL)の基礎知識
2.Building Windows DLLs with MinGW
3.HOWTO Create and Deploy a Sample DLL using MinGW

MinGWによる静的ライブラリの作成と静的リンク

MinGW g++ を使った静的ライブラリの作成方法と静的リンクについて紹介します。静的リンクとは、コンパイル時に実行ファイルとライブラリをリンクすることです。一方、動的リンクとは、実行時に実行ファイルとライブラリをリンクすることです。


静的ライブラリの作成

まず、下記のmodule1.cppとmodule2.cppを作成します。

module1.cpp

int add(int x, int y) {
  return x + y;
}

module2.cpp

int mul(int x, int y) {
  return x * y;
}

module1.cppとmodule2.cppがあるフォルダでバッチファイルarchive.batを実行すると、静的ライブラリlibexample.aが生成されます。その後で、libexample.aをフォルダD:\libに移動させています。静的ライブラリは複数のオブジェクトファイルが一つにまとめられたファイルです。

archive.bat

set path=D:\MinGW\bin
g++ -c module1.cpp
g++ -c module2.cpp
ar r libexample.a module1.o module2.o
move libexample.a D:\lib


実行ファイル(EXE)の作成

呼び出す側のプログラムmain.cppを作成します。

main.cpp

#include <stdio.h>

int add(int, int);
int mul(int, int);

int main() {
  printf("%d\n", add(1, 1));
  printf("%d\n", mul(1, 1));
  return 0;
}

main.cppがあるフォルダでバッチファイルmain1.bat~main3.batを実行すると、実行ファイルmain.exeが生成されます。静的リンクではこの段階で、静的ライブラリlibexample.aが実行ファイルmain.exeに取り込まれます。

main1.batのように-staticを指定すると静的リンクできる全てのライブラリに対して静的リンクを適用するので、今回の場合libexample.aだけでなくC/C++標準ライブラリも静的にリンクされます。
尚、-Lでライブラリのパスを指定し、-lでリンクするライブラリを指定します。コマンドラインオプション-lexampleのexampleはlibexample.aのことです。

main1.bat

set path=D:\MinGW\bin
g++ -static main.cpp -LD:\lib -lexample -o main.exe
strip main.exe

ライブラリを個別に静的リンクするにはmain2.batのようにします。-dn(dynamic no)は静的リンク、-dy(dynamic yes)は動的リンクを表わします。また、-static-libgcc及び-static-libstdc++は、C/C++標準ライブラリを静的リンクするために用います。
尚、今回のプログラムの場合、main1.batとmain2.batが生成するネイティブコードは全く同じです。

main2.bat

set path=D:\MinGW\bin
g++ main.cpp -LD:\lib -Wl,-dn,-lexample -static-libgcc -static-libstdc++ -o main.exe
strip main.exe

main3.batの場合、libexample.aは静的リンク、C/C++標準ライブラリは動的リンクです。このため、実行時にlibgcc_s_dw2-1.dllが必要になります。

main3.bat

set path=D:\MinGW\bin
g++ main.cpp -LD:\lib -lexample -o main.exe
strip main.exe


EXEの実行

バッチファイルrun.batを実行して下さい。尚、D:\MinGW\binにパスを通しているのは、main3.batで生成したmain.exeを実行する際にlibgcc_s_dw2-1.dllが必要になるためです。main1.batとmain2.batで生成したmain.exeでは必要ありません。

run.bat

set path=D:\MinGW\bin
main.exe
pause


参考サイト

1.プログラムで使う静的ライブラリ、共有ライブラリ C言語
2.cc コンパイラオプション
3.C ユーザーズガイド コンパイラオプション
4.GCCの使い方メモ:静的ライブラリを作ってみる
5.MinGWでライブラリを静的リンクする方法
6.ダイナミックリンクとスタティックリンクの混在(MinGW環境)
7.共有ライブラリと静的ライブラリを整理する
8.静的ライブラリと共有ライブラリの整理
9.MinGW GCCでlibcとしてmsvcrt.dll以外を使うまとめ
10.シンボリックリンクはとても便利

配列の共変性

配列の共変性とは、狭い型の配列から広い型の配列への変換(代入も変換の一種)に伴って、広い型の配列の型が狭い型に変わることです。尚、親クラスと子クラスを比較した場合、親クラスが広い型で子クラスが狭い型です。

以下では Java の配列を例にとって考えてみましょう。この例では、Integerクラスが狭い型、Numberクラスが広い型です。Java ではObjectクラスが最も広い型です。

  1. Integer[] integer = {0};
  2. Number[] number = integer;
  3. System.out.println(number[0] instanceof Integer);
  4. number[0] = 0.1;

 1.Integerクラスの配列integerを初期化します。
 2.狭い型(Integerクラス)の配列integerが広い型(Numberクラス)の配列numberに変換(ここでは代入)されます。
 3.広い型(Numberクラス)の配列要素number[0]の型が狭い型(Integerクラス)に変わったのを確認します。
 4.Integerクラスのインスタンスになったnumber[0]に浮動小数点数を代入しているので実行時に例外が発生します。本当はコンパイル時にエラーになって欲しいのですが。。。

 注意)広い型の変数に狭い型の変数を代入できることが共変性ではありません。

実行結果

true
Exception in thread "main" java.lang.ArrayStoreException