ブログ

割とコンピュータよりの情報をお届けします。

コンピュータ

Microsoft Visual Studio Express 2017 for Windows Desktop でDLL作成

Visual Studio Professionalならテンプレートがついていてすぐできるのだが,Expressではdll作成のテンプレートがないので自分で設定しないといけない。

(なお,いったんプロジェクトを作ってしまうとExpressでも使える。)

まずは,コンソールアプリを作るテンプレートを開く。

プロジェクトのプロパティを開き,「C/C++」「プリプロセッサ」「プリプロセッサの定義」を見ると「_CONSOLE」が入っているはずなので削除。

おそらく
_WINDOWS
_USRDLL
TEST_EXPORTS
を追加しないといけない。(TEST_EXPORTSは例えば)

「全般」の構成の種類はダイナミック ライブラリ(.dll)にしなければならない。

例えば,ヘッダファイルは以下のようにする。

#pragma once

#ifdef TEST_EXPORTS
#define TEST_API extern "C" __declspec(dllexport)
#else
#define TEST_API extern "C" __declspec(dllimport)
#endif

TEST_API int test(void);

このヘッダファイルは関数を定義するソースの先頭かstdafx.hで読ませておく必要がある。そして本体ソースは以下のようになる。

#include "stdafx.h"

TEST_API int test(void) {
return 1;
}

プロジェクトのプロパティの[C/C++][詳細設定]の呼び出し規約も注意する必要がある。

≫ Read More

2018/08/06 コンピュータ   TakeMe

python-opcuaのnodeidのつけ方に苦労した

最近 自分で作ったアプリとほかのソフトのつなぎでOPC UAに対応を迫られる場面があって,node opcuaを使用したが,通信が問題なく続いている間は問題がないが,いったん不具合があったときに再接続に失敗する不具合が解消せずpython-opcuaに乗り換えることになった。ところが,サンプルを見ても"ns=2;i=3"などのnodeid?のつけ方がわからずに苦労した。

さんざん調べていたら,偶然
myvar2 = myobj.add_variable("ns=2;i=3", "takeme", True)
などとすると良いことが分かった。

server_minimal.pyのサンプルから以下のようにすれば変更できる。

    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
から
    myvar = myobj.add_variable("ns=2;i=3", "MyVariable", 6.7)
へ変更

ただし,上の書式でコールして勝手に追加されるnodeidとの重複には十分に注意しなければならない。

先にadd_variable("ns=2;i=3", "MyVariable",  value)の書式で指定したidは後からadd_variable(idx, "MyVariable",  value)の書式で指定したときには重複しないように避けられる。逆の順番でコールした場合には重複は避けられない。"ns=2;i=xxx"で固定したいものを先にコールして固定しないといけない。

クライアントソフトによっては名前を見ずにnodeidで一意性を確認している場合があるので,サブスクライブの設定の時についていたnodeidは使い続ける限り,ずーっと維持されなくてはならない。サーバが再起動しても同じnodeidが付かないと別の変数と認識されてしまう。

≫ Read More

2018/08/05 コンピュータ   TakeMe

CSSのtransitionが効かない項目もある

CSSのtransitionなるものを調べていたら一部の項目は効かないことが分かった。

CSSにいつの間にかtransitionなるものが追加されていた。

アニメーションが非常に簡単に実装できるようになった。

しかし,あらゆる項目がtransitionでアニメーションされるわけではないようだ。この例での,line-heightは遷移前と遷移後それぞれに値の定義がないとアニメーションにならない。rightとかcenterとかの遷移もアニメーションにならないみたい(瞬時に適用される)。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
.container {
  width: 100%;
  height: 100%;
  filter: drop-shadow(4px 4px 10px rgba(0,0,0,0.8));
}

.sample {
  transform: rotate(0deg);
  clip-path: circle(40% at center);
  background: skyblue;
  position:absolute;
  transition: 2s;
}

.sample720 {
  transform: rotate(720deg);
  clip-path: circle(40% at center);
  background: skyblue;
  position:absolute;
  transition: 2s;
}

.rotate0 {
  background: cornsilk;
  transform: rotate(0deg);
  transition: 2s;
  position:absolute;
  text-align:center;
  vertical-align:middle;
  line-height: 200px;
}

.rotate360 {
  background: skyblue;
  transform: rotate(360deg);
  transition: 2s;
  position:absolute;
}

</style>
</head>
<body>
<div class="container">
  <div class="sample" style="left:2vw;top:5vh;margin-top:6vh;width:200px;height:200px;text-align:center;vertical-align:middle;line-height: 200px;">TEST1</div>
  <div class="rotate0" style="left:20vw;top:10vh;width:200px;height:200px;">TEST2</div>
</div>
<script>
function Transition() {
  var element = document.querySelector("div.rotate0");
  if (element) {
    element.className = "rotate360";
  } else {
    element = document.querySelector("div.rotate360");
    element.className = "rotate0";
  }
  
  element = document.querySelector("div.sample");
  if (element) {
    element.className = "sample720";
  } else {
    element = document.querySelector("div.sample720");
    element.className = "sample";
  }
  
  return element;
}

setInterval(Transition, 2000);
</script>
</body>
</html>
TEST

≫ Read More

2018/08/04 コンピュータ   TakeMe

plotly.jsを使ってみた

plotly.jsはオープンソースになっていると聞いて使ってみた。

ヒートマップで砂嵐を表現してみた。

この例はかなりCPUの負荷が大きい。

しかし,簡単に一応動かせるレベルで仕上がる。

(layoutのheightは指定しなければ勝手に決められる。)

heatmap以外にたくさん格好の良いチャートが作れるらしい。
heatmapでreact()を実行する場合には注意が必要。dataのオブジェクトの変更を見て更新しているようだ。
つまり,下の例では,data = [   {     zmin:0,     zmax:10,     z: z,      type: 'heatmap'   } ];としているがこの,zのオブジェクトの参照を変えずにzの要素だけを変更してreact('mydDiv', data)など実行した場合には表示の更新が後回しにされる可能性が高い。
変更を監視して必要があれば更新するのだが,どうも変更監視のコードの作り込みが簡易的に(よりコンピュータに負荷をかけないように)作られているようだ。

<!DOCTYPE html>
<html>
<head>
<script src="js/plotly.min.js"></script>
</head>
<body>
<div id="myDiv"></div>
<script>
var layout = {
  colorbar: {
    autorange: false,
    range: [0, 10]
  },
  height: 600
};

var z = [];
for (var i = 0; i < 250; i++) {
  var zz = [];
  for (var j = 0; j < 120; j++) {
    zz.push(10 * Math.random());
  }
  z.push(zz);
}
var data = [
  {
    zmin:0,
    zmax:10,
    z: z, 
    type: 'heatmap'
  }
];

Plotly.newPlot('myDiv', data, layout);

setInterval(function() {
  var z = [];
  for (var i = 0; i < 250; i++) {
    var zz = [];
    for (var j = 0; j < 120; j++) {
      zz.push(10 * Math.random());
    }
    z.push(zz);
  }
  var data = [
    {
      zmin:0,
      zmax:10,
      z: z,
      type: 'heatmap'
    }
  ];
  Plotly.react('myDiv', data, layout);
}, 500);

</script>
</body>
</html>

≫ Read More

2018/08/03 コンピュータ   TakeMe

Node.jsでtcpサーバとクライアント作成の試行

前の記事でSocket.ioばかり使用していたが,とりあえずsocketでもよいのではないかと思って調べていたら,参考になりそうな記事があった。

参考をもとに,ほとんど構造を変えないように注意しながらサーバ側とクライアント側を作成させてもらった。

サーバ側 こっちは作りやすい。

var net = require('net');
var port = 3000;
var server = net.createServer(function (connection) {
  console.log('server: created');
  connection.on('data', function(data){
    connection.write('server: Repeating: ' + data);
  });
  connection.on('close', function(){
    console.log('server: client closed connection');
  });
  connection.on('error', function(){
    console.log('server: client made error');
  });
}).listen(port);
console.log('listening on port 3000');

クライアント側はもしNode.jsなら以下のようになるが,本来socket.connect()にはcallbackを渡すことができる。そこでwrite()を入れていたが,このプログラムはいったん接続が切れたら再接続を図ろうとしている。ところが,connect()に渡したcallbackは次に接続ができるようになった時に1回実行されるので,ずーっと接続ができない状態であるとき接続が始まると,一気に大量のパケットが流れ出す。非常に問題の多いコードになっているので一応コメントアウトしている。

最も目的はPythonなどとの接続であろうからこのクライアント側コードは使わなくてもよい。

var net = require('net');

var port = 3000;
var client = new net.Socket();

client.setEncoding('utf8');

var connect = function () {
  client.connect(port, 'localhost'/*, function() {
    console.log('client: connected to server');
    //client.write('connect');
  }*/);
}

connect();

process.stdin.resume();
process.stdin.on('data', function (data) {
  client.write(data);
});

client.on('data', function (data) {
  console.log('client: ' + data);
});

client.on('close', function () {
  console.log('client: connection is closed');
  setTimeout(connect, 6000);
});

client.on('error', function () {
  console.log('client: made error');
});

もっともこのコードでも,connect()の対応は不完全で接続が確立できないまま何度もconnect()の実行を繰り返すと次第にメモリ使用量が増えていく。

クライアント側でNode.jsで再接続を実装する場合には,node-net-reconnectなどの使用を検討された方がよいかもしれない。

≫ Read More

2018/07/29 コンピュータ   TakeMe

vue-cliでインストールしたwebpackでnpm run buildで用意したコンテンツをCefSharpで使用

vue-cliでインストールしたwebpackでnpm run buildで用意したコンテンツをCefSharpで使用するときの注意点。

まずCefSharpの方だが,最近CefSharpのバージョンが65に上がったが概ねここに書いた記事のまま使用できる(というかまだパッケージ自体はAny CPU対応を謳っているが,これをインストールしただけでAny CPU対応の記述をプロジェクトファイルに追記していないと使えもしない状態が続いている)。

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var browser = new CefSharp.Wpf.ChromiumWebBrowser();
            // アドレスの取得
            String page = string.Format(@"{0}\dist\index.html", StartupPath);
            BrowserSettings browserSettings = new BrowserSettings();
            browserSettings.FileAccessFromFileUrls = CefState.Enabled;
            browserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
            browser.BrowserSettings = browserSettings;
            // アドレス設定
            browser.BrowserSettings.AcceptLanguageList = "ja-JP";
            browser.Address = page;
            Content = browser;
        }

        // 実行ファイルのディレクトリ取得
        public string StartupPath
        {
            get
            {
                return System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(Environment.GetCommandLineArgs()[0]));
            }
        }
    }

Windows Formsが必要ならここに書いた(差分が必要)。

そして,vue-cliでコンテンツを用意する方法だが,コマンドプロンプトでnpm run devを実行するとdistフォルダにコンテンツが生成されるが,ここにあるようにconfig/index.jsのbuildのオブジェクトのassetsPublicPathを'./'に変更する必要がある。

≫ Read More

2018/07/29 コンピュータ   TakeMe

Pythonでsocket.io 2.0のクライアントはsocketIO-client-nexusに限定されているかもしれない

Python用のsocket.ioのクライアントは結構更新が遅くなっていて,今ではsocket.io 2.xに対応していないものばかりになってしまった。

この前の記事にあるsocket.ioの例につなげるクライアントだけを書いてみた。

まず,socketIO-client-nexusにならsocket.io 2.xの対応が盛り込まれている。(リンク先にもあるが,それ以外のsocket.ioのクライアントライブラリはsocket.io 1.xにしか対応してないことが多いよう。)

ただし,すべてが実装されているかどうかはわからない。

とりあえず,pip install socketIO-client-nexusを実行してから,つくってみた例だが,以下のようになる。

from socketIO_client_nexus import SocketIO, LoggingNamespace

def on_connect():
    print('connect')

def on_disconnect():
    print('disconnect')

def on_reconnect():
    print('reconnect')

def on_date_response(*args):
    print('on_date', args)

socketIO = SocketIO('localhost', 8081, LoggingNamespace)
socketIO.on('connect', on_connect)
socketIO.on('disconnect', on_disconnect)
socketIO.on('reconnect', on_reconnect)

# Listen
socketIO.on('date', on_date_response)
socketIO.emit('test', {'value': 'test3'})
socketIO.wait(seconds=10)

≫ Read More

2018/07/28 コンピュータ   TakeMe

vue-cliでインストールしたwebpackなどでnpm run buildでできたファイルイをfile://で使う

npm run build
を実行した後,Opening index.html over file:// won't work
と表示が出ていたのでできないのかと思っていたが,

これは,config/index.jsのbuildのオブジェクトのassetsPublicPathを'./'に変更すると回避できる
つまり,distのindex.htmlがドキュメントルートに来なくなても,file://であっても使用できるようになる。

最近のChromeはfile://〇〇であってもhttpsを使用していない旨の警告「このサイトへの接続は保護されていません」と表示される。

ちなみにwepack-dev-serverを使用する場合の設定はconfig/index.jsの上の方に devというオブジェクトに記述する。

ポート番号は標準は8080だが,変更できる。

 

ところで標準ではwebpack-dev-serverにネットワーク内の他のクライアントからアクセスできない。おそらくhost: 'localhost'が原因なのではと思っているが,うまく回避できていない。

≫ Read More

2018/07/26 コンピュータ   TakeMe

vue-cliをnpm install -D vue-cliでインストールに失敗

vue-cliのインストールの説明ではnpm install -g vue-cliでインストールと書かれているが,npm install -D vue-cliでできないのかを確認していてハマった。

先にうまくいった手順の例を説明すると(node-v10.2.1-win-x64)

npm init -y
npm install -D vue-cli
npm install -D vue
npm install -D webpack
npm install -D webpack-dev-server
npx vue init webpack my-project
cd my-project
npm install
npm run dev

たぶん npm install -D vue,npm install -D webpack,npm install -D webpack-dev-serverなどは関係ないと思われるが念のためここで実行しておいた。

npm init -y

の後にpackage.jsonの内容をいじってからnpm install -D vue-cliを実行しているとnpx vue init webpack my-projectで警告がでてnpm installで失敗してしまっていた。(3週間考えた挙句棚上げにしていた。)

ただし,うまくいった理由はpackage.jsonをいじらずに次の操作に行ったからか?
vueやwebpackを明示的にインストールしないといけないのかネットワークの都合なのかは定かではない。

インストール自体は数十分間で結構時間がかかる操作だった。(回線速度による)

≫ Read More

2018/07/26 コンピュータ   TakeMe

MongoDBの周辺スクリプトの作成の続き

MongoDB(特に4.0.0のWindows用)の設定関係のファイルを引き続き作っていた。

サンプル作成が異常に面倒である。
今回もファイルサイズが大きすぎて本文に埋め込めなくなってしまった。

環境変数の読み込み用ファイルenv.bat
(cmdのショートカットのリンク先にC:\Windows\System32\cmd.exe /k "C:\mongodb-4.0.0\env.bat"などと設定して使うのも)

@echo off
set "PATH=%~dp0;%PATH%"
SET PATH=%PATH%;C:\mongodb-4.0.0\bin

setlocal enabledelayedexpansion
pushd "%~dp0"

popd
endlocal

 

MongoDBをスタートするスクリプト mongodb_start.cmd

mongod --config "C:\mongodb-4.0.0\mongod.cfg"

 

MongoDBをWindowsサービスにするスクリプト mongodb_install_service.cmd

set service_name=MONGODB_TAKEME_APP
mongod --install --config "C:\mongodb-4.0.0\mongod.cfg" --serviceName %service_name% --serviceDisplayName "MONGODB FOR TAKEME_APP" --serviceDescription "MongoDB 4.0.0 for TakeMe Applications."
net start %service_name%

 

MongoDBをWindowsサービスから削除する mongodb_remove_service.cmd

set service_name=MONGODB_TAKEME_APP
net stop %service_name%
mongod --remove --serviceName "MONGODB_TAKEME_APP"

 

MongoDBの設定ファイル mongod.cfg
ユーザ入れかえ mongodb_change_username.cmd
(username.jsに新しいユーザ名usernameOld.jsに古いユーザ名を入れて実行)

set service_name=MONGODB_TAKEME_APP
mongo localhost:27017 Init0.js
net stop %service_name%
net start %service_name%
mongo localhost:27017 Init1.js

管理ユーザで実行しないと使えないけど参考のファイルなど添付しておきます(Search consoleで警告が出たので中止)。

 

特にユーザ交換スクリプトは以下のようにInit0.jsを実行する。

conn = new Mongo("localhost:27017");
db  = conn.getDB("admin");
load('usernameOld.js');

db.auth(username, password);

var lstUsers = db.getUsers();
var users = [];
for (var i = 0; i < lstUsers.length; i++) {
  users.push(lstUsers[i].user);
}

db = conn.getDB('TAKEME_APP');
db.auth(username, password);
for (var i = 0; i <users.length; i++) {
  db.dropUser(users[i]);
}

db = conn.getDB('admin');
db.auth(username, password);
for (var i = 0; i <users.length; i++) {
  db.dropUser(users[i]);
}

 

設定を行う本体スクリプトInit1.js

conn = new Mongo("localhost:27017");
db  = conn.getDB("admin");
load('username.js');

db.createUser(
  {
    user: username,
    pwd: password,
    roles: [
      {
        "role": "root",
        "db" : "admin"
      },
      {
        "role": "userAdmin",
        "db" : "admin"
      },
      {
        "role": "hostManager",
        "db" : "admin"
      }
    ]
  }
);

db.auth(username, password);

var lstUsers = db.getUsers();
var users = [];
for (var i = 0; i < lstUsers.length; i++) {
  if (lstUsers[i].user !== username)
    users.push(lstUsers[i].user);
}

for (var i = 0; i <users.length; i++) {
  db.dropUser(users[i]);
}


db = conn.getDB('TAKEME_APP');
for (var i = 0; i < users.length; i++) {
  db.dropUser(users[i]);
}

db.createUser(
  {
    user: username,
    pwd: password,
    roles: [
      {
        "role": "readWrite",
        "db" : "TAKEME_APP"
      }
    ]
  }
);


注意はmongo shellでJavaScriptを実行する場合,conn = new Mongo("localhost:27017"); db = conn.getDB("admin");などを使ってdbを指定してこないといけない。use admin;などでdbが指定できるコンソールと若干異なる。

≫ Read More

2018/07/22 コンピュータ   TakeMe