PostgreSQLをLinuxでソースコードからビルドして利用する方法

August 17,2017 1:23 AM
Category:[PostgreSQL]
Tag:[]
Permalink

PostgreSQLをLinuxでソースコードからビルドして利用する方法を紹介します。

1.PostgreSQLソースのダウンロード

PostgreSQLのソースは、最新バージョンである下記のページにアクセスします(2017年8月現在)。

このページにある、"postgresql-9.6.3.tar.gz"をダウンロード。

2.ソースコードのビルド

ソースコードをビルドします(コマンドは赤色)。

# ./configure --without-readline
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking which template to use... linux
 :
config.status: linking src/backend/port/dynloader/linux.h to src/include/dynloader.h
config.status: linking src/include/port/linux.h to src/include/pg_config_os.h
config.status: linking src/makefiles/Makefile.linux to src/Makefile.port
# make
make -C src all
make[1]: ディレクトリ `/home/y-araki/postgresql-9.6.3/src' に入ります
make -C common all
make[2]: ディレクトリ `/home/y-araki/postgresql-9.6.3/src/common' に入ります
make -C ../backend submake-errcodes
make[3]: ディレクトリ `/home/y-araki/postgresql-9.6.3/src/backend' に入ります
prereqdir=`cd 'utils/' >/dev/null && pwd` && \
          cd '../../src/include/utils/' && rm -f errcodes.h && \
          ln -s "$prereqdir/errcodes.h" .
make[3]: ディレクトリ `/home/y-araki/postgresql-9.6.3/src/backend' から出ます
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -O2 -DFRONTEND -I../../src/include -D_GNU_SOURCE  -DVAL_CONFIGURE="\"'--without-readline'\"" -DVAL_CC="\"gcc\"" -DVAL_CPPFLAGS="\"-DFRONTEND -D_GNU_SOURCE\"" -DVAL_CFLAGS="\"-Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -O2\"" -DVAL_CFLAGS_SL="\"-fpic\"" -DVAL_LDFLAGS="\"-L../../src/common -Wl,--as-needed -Wl,-rpath,'/usr/local/pgsql/lib',--enable-new-dtags\"" -DVAL_LDFLAGS_EX="\"\"" -DVAL_LDFLAGS_SL="\"\"" -DVAL_LIBS="\"-lpgcommon -lpgport -lz -lrt -lcrypt -ldl -lm  \""  -c -o config_info.o config_info.c
 :
make -C config all
make[1]: ディレクトリ `/home/y-araki/postgresql-9.6.3/config' に入ります
make[1]: `all' に対して行うべき事はありません.
make[1]: ディレクトリ `/home/y-araki/postgresql-9.6.3/config' から出ます
All of PostgreSQL successfully made. Ready to install.
# make install
make -C src install
make[1]: ディレクトリ `/home/y-araki/postgresql-9.6.3/src' に入ります
make -C common install
make[2]: ディレクトリ `/home/y-araki/postgresql-9.6.3/src/common' に入ります
make -C ../backend submake-errcodes
 :
make[1]: ディレクトリ `/home/y-araki/postgresql-9.6.3/src' から出ます
make -C config install
make[1]: ディレクトリ `/home/y-araki/postgresql-9.6.3/config' に入ります
/bin/mkdir -p '/usr/local/pgsql/lib/pgxs/config'
/usr/bin/install -c -m 755 ./install-sh '/usr/local/pgsql/lib/pgxs/config/install-sh'
/usr/bin/install -c -m 755 ./missing '/usr/local/pgsql/lib/pgxs/config/missing'
make[1]: ディレクトリ `/home/y-araki/postgresql-9.6.3/config' から出ます
PostgreSQL installation complete.

3.DBD::Pgインストール

Perlで利用したいため、DBD::Pgをインストールしました。

CPANからダウンロードしたDBD-Pg-3.6.2のアーカイブをLinux上で展開し、インストールします。

# cd DBD-Pg-3.6.2
# ls -l
合計 640
-rw-r--r--. 1 1000 1000  59734  5月 23 23:23 2017 Changes
drwxr-xr-x. 2 1000 1000   4096  5月 23 23:24 2017 LICENSES
-rw-r--r--. 1 1000 1000    747  4月 20 08:44 2017 MANIFEST
-rw-r--r--. 1 1000 1000    359  4月 20 08:44 2017 MANIFEST.SKIP
-rw-r--r--. 1 1000 1000   1675  5月 23 23:23 2017 META.yml
-rw-r--r--. 1 1000 1000  11177  5月 23 23:23 2017 Makefile.PL
-rw-r--r--. 1 1000 1000   8567  3月 29 07:03 2017 Pg.h
-rw-r--r--. 1 1000 1000 176872  5月 23 23:23 2017 Pg.pm
-rw-r--r--. 1 1000 1000  19749  4月  3 23:46 2017 Pg.xs
-rw-r--r--. 1 1000 1000  12217  5月 23 23:23 2017 README
-rw-r--r--. 1 1000 1000  30715  4月 26 11:19 2017 README.dev
-rw-r--r--. 1 1000 1000   2436  3月 29 06:10 2017 README.win32
-rw-r--r--. 1 1000 1000   3734  5月 23 23:24 2017 SIGNATURE
-rw-r--r--. 1 1000 1000   1887  3月 31 09:03 2017 TODO
-rw-r--r--. 1 1000 1000 162413  5月 23 23:22 2017 dbdimp.c
-rw-r--r--. 1 1000 1000  11296  4月  5 21:36 2017 dbdimp.h
-rw-r--r--. 1 1000 1000   2016  3月 29 06:10 2017 dbivport.h
drwxr-xr-x. 3 1000 1000   4096  5月 23 23:24 2017 lib
-rw-r--r--. 1 1000 1000  34222  4月 20 08:37 2017 quote.c
-rw-r--r--. 1 1000 1000   1501  3月 29 06:10 2017 quote.h
drwxr-xr-x. 3 1000 1000   4096  5月 23 23:24 2017 t
-rwxr-xr-x. 1 1000 1000   5419  4月  7 23:02 2017 testme.tmp.pl
-rw-r--r--. 1 1000 1000  42748  3月 29 07:03 2017 types.c
-rw-r--r--. 1 1000 1000   6198  3月 29 06:23 2017 types.h
-rw-r--r--. 1 1000 1000   2487  3月 29 06:10 2017 win32.mak
# perl Makefile.PL
Configuring DBD::Pg 3.6.2
PostgreSQL version: 90603 (default port: 5432)
POSTGRES_HOME: (not set)
POSTGRES_INCLUDE: /usr/local/pgsql/include
POSTGRES_LIB: /usr/local/pgsql/lib
OS: linux
Checking if your kit is complete...
Looks good
Warning: prerequisite Time::HiRes 0 not found.
Using DBI 1.636 (for perl 5.010001 on x86_64-linux-thread-multi) installed in /usr/local/lib64/perl5/auto/DBI/
Writing Makefile for DBD::Pg
# make
cp lib/Bundle/DBD/Pg.pm blib/lib/Bundle/DBD/Pg.pm
cp Pg.pm blib/lib/DBD/Pg.pm
/usr/bin/perl -p -e "s/~DRIVER~/Pg/g; s/^do\(/dontdo\(/" /usr/local/lib64/perl5/auto/DBI/Driver.xst > Pg.xsi
/usr/bin/perl /usr/share/perl5/ExtUtils/xsubpp  -typemap /usr/share/perl5/ExtUtils/typemap  Pg.xs > Pg.xsc && mv Pg.xsc Pg.c
gcc -c  -I/usr/local/pgsql/include -I/usr/local/lib64/perl5/auto/DBI -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DPGLIBVERSION=90603 -DPGDEFPORT=5432 -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic  -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc -DVERSION=\"3.6.2\" -DXS_VERSION=\"3.6.2\" -fPIC "-I/usr/lib64/perl5/CORE"   Pg.c
 :
chmod 755 blib/arch/auto/DBD/Pg/Pg.so
cp Pg.bs blib/arch/auto/DBD/Pg/Pg.bs
chmod 644 blib/arch/auto/DBD/Pg/Pg.bs
Manifying blib/man3/Bundle::DBD::Pg.3pm
Manifying blib/man3/DBD::Pg.3pm
# make install
Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
Installing /usr/local/lib64/perl5/auto/DBD/Pg/Pg.so
Installing /usr/local/lib64/perl5/auto/DBD/Pg/Pg.bs
Installing /usr/local/lib64/perl5/Bundle/DBD/Pg.pm
Installing /usr/local/lib64/perl5/DBD/Pg.pm
Installing /usr/local/share/man/man3/Bundle::DBD::Pg.3pm
Installing /usr/local/share/man/man3/DBD::Pg.3pm
Appending installation info to /usr/lib64/perl5/perllocal.pod

4.PostgreSQLユーザアカウント作成

PostgreSQL用のアカウントを作成します。下記のページを参考にしました。

17.1. PostgreSQLユーザアカウント

# groupadd postgres
# useradd -d /home/postgres -g postgres -s /bin/tcsh postgres
# passwd postgres
ユーザー postgres のパスワードを変更。
新しいパスワード:
よくないパスワード: 辞書の単語に基づいています
新しいパスワードを再入力してください:
passwd: 全ての認証トークンが正しく更新できました。
# chown postgres /usr/local/pgsql
# ls -l
合計 48
drwxr-xr-x. 17 root     root 4096  4月 10 11:17 2017 apache2
drwxr-xr-x.  2 root     root 4096  7月 27 10:52 2017 bin
drwxr-xr-x.  2 root     root 4096  9月 23 20:50 2011 etc
drwxr-xr-x.  2 root     root 4096  9月 23 20:50 2011 games
drwxr-xr-x.  2 root     root 4096  4月 10 10:08 2017 include
drwxr-xr-x.  4 root     root 4096  4月 10 10:08 2017 lib
drwxr-xr-x.  3 root     root 4096  4月 10 11:30 2017 lib64
drwxr-xr-x.  2 root     root 4096  9月 23 20:50 2011 libexec
drwxr-xr-x.  7 postgres root 4096  7月 27 14:10 2017 pgsql
drwxr-xr-x.  2 root     root 4096  9月 23 20:50 2011 sbin
drwxr-xr-x.  8 root     root 4096  4月 10 11:30 2017 share
drwxr-xr-x.  2 root     root 4096  9月 23 20:50 2011 src
# su - postgres
$ setenv LD_LIBRARY_PATH /usr/local/pgsql/lib
$ set path = ( /usr/local/pgsql/bin $path )

5.データベースクラスタの作成

PostgreSQLユーザでデータベースクラスタを作成します。下記のページを参考にしました。

17.2. データベースクラスタの作成

$ initdb -D /usr/local/pgsql/data
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
 
The database cluster will be initialized with locale "ja_JP.UTF-8".
The default database encoding has accordingly been set to "UTF8".
initdb: could not find suitable text search configuration for locale "ja_JP.UTF-8"
The default text search configuration will be set to "simple".
 
Data page checksums are disabled.
 
creating directory /usr/local/pgsql/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
 
WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
 
Success. You can now start the database server using:
 
    pg_ctl -D /usr/local/pgsql/data -l logfile start

6.データベースサーバの起動

データベースサーバを起動します。起動方法はいろいろあるようですが、下記のページを参考にしました。

17.3. データベースサーバの起動

$ pg_ctl -D /usr/local/pgsql/data -l logfile start
server starting

7.データベースユーザの作成

データベース用のユーザ"mtuser"を作成します。

$ createuser -P --no-adduser --no-createdb --no-createrole mtuser
Enter password for new role:
Enter it again:

8.データベースの作成

データベース"hoge"を作成します。

$ createdb --owner mtuser hoge

9.その他

ここまでの作業でMovableTypeをPostgresQLで動かせると思ったのですが、起動しても「データベースモジュールが見つかりません」となり、インストールしたはずのDBD::Pgが表示されます。

postgresql.confに下記の1行を追加し、ldconfigを実施することで解消しました。

下記のページを参考にしました。

15.6. インストール後の設定作業

# cd /etc/ld.so.conf.d
# vim postgresql.conf

下記の1行を追加。
--------------------
/usr/local/pgsql/lib
--------------------

# /sbin/ldconfig

これを行わないとMovableTypeの画面で「再試行」を実施しても状況が変わりません。

10.ノウハウ

"pg_ctl -D /usr/local/pgsql/data -l logfile start"はバックグラウンド起動しません。

バックグラウンド起動すると正常に起動されません。

上の状態に気が付かずにcreateuserすると、「could not connect to database postgres: could not connect to server」というエラーになります(下)。

$ pg_ctl -D /usr/local/pgsql/data -l logfile start 2>&1 &
[1] 6217
[postgres@mnet-host11 ~]$ createuser
createuser: could not connect to database postgres: could not connect to server: そのようなファイルやディレクトリはありません
        Is the server running locally and accepting
        connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
[1]  + 1で終了しました pg_ctl -D /usr/local/pgsql/data -l logfile start 2 >& 1

11.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

FinaleでD.C.とコーダマーク(Coda)を設定する方法

August 6,2017 12:03 AM
Category:[Finale]
Tag:[Finale]
Permalink

FinaleでD.C.とコーダマーク(Coda)を設定する方法を紹介します。

D.C. al Codaとコーダマーク
D.C. al Coda

コーダマーク
コーダマーク

1.問題点

下の楽譜の2小節目に「D.C. al Coda」という記号を挿入したいです。

D.C. al Coda

こちらは1カッコの直前にコーダマークを設定したいです。

コーダマーク

また、再生時も先頭に戻ってコーダマークでジャンプさせたいのですが設定方法が分かりません。

ということで、FinaleでD.C.とコーダマーク(Coda)を設定する方法を紹介します。

2.D.C.とコーダマーク(Coda)を設定する

まずD.C.から設定します。反復記号ツールをクリック。

反復記号ツール

D.C.したい小節をダブルクリック。ここでは青色に反転している小節をダブルクリックしています。

D.C.したい小節をダブルクリック

「D.C. al Coda」を選択して「選択」をクリック。この手順では楽譜に「D.C. al Coda」が表示されますが、表示内容を変更したい場合は先に「作成」をクリックします。

「D.C. al Coda」を選択

右側の「飛び越し先」で「指定小節」に「1」を設定して「OK」をクリック。

飛び越し先

楽譜に「D.C. al Coda」が表示されます。

楽譜に「D.C. al Coda」が表示

記号の右側の□をドラッグして位置を調整すれば完了です。

位置を調整

次にコーダマーク(Coda)を設定します。反復記号ツールをクリックした状態でコーダマークを設定したい小節をダブルクリック。ここでは青色に反転している小節をダブルクリックしています。

Codaを設定したい小節をダブルクリック

コーダマークを選択して「選択」をクリック。

コーダマークを選択

左側の「動作」から「x回通過したら飛ぶ」を選択し、ここでは「3(繰り返し+D.C.の計3回)」を設定、右側の「飛び越し先」で「指定小節」に「34(さきほどのD.C.の次の小節)」を設定して「OK」をクリック。

動作

楽譜にコーダマークが表示されます。

楽譜にコーダマークが表示

コーダマーク右側の□をドラッグして位置を調整すれば完了です。

位置を調整

「D.C. al Coda」の右側のコーダマークは前述のコーダマーク設定とほぼ同じで、「文字反復記号の機能設定」画面の「動作」で「なにもしない」を選択すればOKです。

動作

また、再生も期待通りの動作になりました。

Comments [0] | Trackbacks [0]

「MovableTypeを導入したときに参考になる記事まとめ」で紹介されました

August 1,2017 12:03 AM
Category:[Movable Type]
Tag:[movabletype]
Permalink

レバテックキャリアさんの記事「MovableTypeを導入したときに参考になる記事まとめ」で当ブログの記事を紹介して頂きました。

MovableTypeを導入したときに参考になる記事まとめMovableTypeを導入したときに参考になる記事まとめ

紹介して頂いたのは、2014年に投稿した「Movable Typeプラグイン一覧」です。

MovableTypeを導入したときに参考になる記事まとめ

そういえば2014年はMTのプラグインを月に1-2本のペースで作っていて、このときは18個のプラグインをリリースしていました。

その他、紹介されている記事は下記です。

  • Movable Typeの動的生成と静的生成について
  • Movable TypeとWordPressの比較
  • お手軽スパム対策
  • MovableType6に人気記事ランキングをつける方法
  • ギャラリーサイトの高負荷アップロードを最適化した方法

気になる方は上記記事を是非ご覧ください。

記事元のレバテックキャリアさんですが、IT・Web業界のエンジニア・クリエイターを専門とする転職エージェントです。

最新の技術情報や業界動向に精通したキャリアアドバイザーが年収・技術志向・今後のキャリアパス・ワークライフバランスなど、一人ひとりの希望に寄り添いながら転職活動をサポートされているようです。

Comments [0] | Trackbacks [0]

Outlookでメールを保存する方法

July 27,2017 12:03 AM
Category:[Outlook]
Tag:[Outlook]
Permalink

Outlookでメールを保存する方法を紹介します。

1.問題点

Outlookでメールがたまってきました。

一部のメールをアーカイブなどしたいのですが、方法がわかりません。

ということでOutlookでメールを保存する方法を紹介します。

2.Outlookでメールを保存する

「ファイル」タブをクリック。

「ファイル」タブ

「情報」タブをクリック。

「情報」タブ

「クリーンアップツール」をクリックして、「古いアイテムの整理」をクリック。

クリーンアップツール

整理したいアイテムを選択し、「以下の日付より古いアイテムを対象とする」の日付を選択し、移動先ファイルを指定します。

ファイルの拡張子は".pst"です。

移動先ファイルを指定

OKをクリックしたら保存が開始します。600件ほどのメールでしたが、保存が完了するまでに数分かかりました。

保存されたファイルは「保存先」というツリーから閲覧することができます。

保存先

Comments [0] | Trackbacks [0]

C++クラスのstatic変数を初期化する

July 21,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C++クラスのstatic変数を初期化する方法を紹介します。

1.はじめに

C++クラスのメンバ変数は普通、newでインスタンスを作る際に初期化するのですが、staticな変数で初期化は一度だけ行いたいという状況が発生しました。

ということでその要件を満たすためのサンプルを作ってみました。

2.staticな変数を1度だけ初期化する

具体的には、newの前にstatic変数を初期化し、そのあとインスタンスを作るというものです。

sample.h

class Sample {
private:
    int bar;
public:
    static int foo;
    Sample(int number);
    void display();
};

sample.cpp

#include <iostream>
#include "sample.h"
 
int Sample::foo;
 
Sample::Sample(int number) {
    bar = number;
}
void Sample::display() {
    std::cout << foo << " " << bar << std::endl;
}

test.cpp

#include "sample.h"
 
int main() {
    Sample::foo = 999;
    Sample* a = new Sample(100);
    a->display();
    return 0;
}

実行

% g++ sample.cpp test.cpp
% ./a.out
999 100

ということで、newする前に初期化したstatic変数をインスタンスからアクセスしても値が保持されていることが確認できました。

サンプルではpublicにして、外部から直接アクセスしていますが、static関数を用意すればprivateでも大丈夫だと思います。

Comments [0] | Trackbacks [0]

Workflowプラグイン(多段階承認・日時指定・グループ選択・複数承認版)リリース

July 19,2017 12:33 AM
Category:[ワークフロー]
Tag:[]
Permalink

本ブログで公開中のMovable Type用「Workflowプラグイン」の多段階承認版に、日時指定・グループ選択・複数承認機能を追加した版をリリースします。

イメージ
イメージ

以下、主な機能について紹介します。

1.日時指定承認

既存のWorkflowプラグインでは日時指定承認が行えませんでしたが、新しくリリースしたWorkflowプラグインでは最終承認者の日時指定承認が行えます。

日時指定承認

公開後の日時指定承認も可能です。

2.複数承認

既存のWorkflowプラグインでは、通常の1段階承認および多段階承認について、それぞれの段階で1名しか承認行為を行えませんでしたが、新しくリリースしたWorkflowプラグインでは2名以上が承認行為を行えるようになりました(その順位に登録された承認者が全員承認しないと、次承認者が承認を行えないか、記事の公開が行われません)。

複数承認設定は、承認者作成画面にある「複数承認」の項目を設定します。

複数承認

承認者の設定状況確認や内容の修正は、「ワークフロー」→「承認者一覧」の管理画面から行えます。

承認者一覧

承認時、他の同順位承認者が未承認の場合、承認エリアに「現在同順位承認者の承認待ちです。」というメッセージを表示します。

メッセージ

3.グループ選択

既存のWorkflowプラグインでは、多段階設定で1つのグループしか作成できませんでしたが、新しくリリースしたWorkflowプラグインでは複数のグループを作成・選択できるようになりました。

選択方法は、ライターがステータスを「未公開(承認待ち)」にすると「承認依頼」エリアに「承認グループ」というグループ選択用プルダウンが表示されるので、ここから選択します(このプルダウンを選択しない状態で承認依頼すると警告が表示されます)。

グループ選択

グループを選択すると、プルダウンメニューの下に承認依頼メールの送信ユーザーが表示されます。

グループ選択

承認者が承認依頼または承認・差し戻しするときの記事編集画面およびプレビュー画面では、ライターの選択したグループが固定された状態で表示されます。選択されたグループに所属していない承認者は、記事の承認はできません。

承認者

「ツール」→「プラグイン」→「Workflow」→「設定」で「ライターによる承認グループ変更」を「使用する」にすれば、ライターは公開された記事の承認依頼時にグループを変更できるようになります。

ライターによる承認グループ変更

グループ作成方法は、グループ設定を行いたいウェブサイトまたはブログ管理画面の「ツール」→「プラグイン」→「Workflow」→「設定」をクリックし、「グループ機能」のプルダウンから「使用する」を選択して「変更を保存」をクリック。

グループ機能

グループ設定を行いたいウェブサイトまたはブログ管理画面の「ワークフロー」→「グループ新規作成」をクリック。

グループ新規作成

下記の項目を設定して「保存」をクリック。

  • グループ名:グループ名を入力。ここで入力した名称がライターのグループ選択プルダウン等に反映されます
  • グループID:グループ名に対応する任意のIDを半角英数・アンダーバーで入力
  • 説明:グループの説明を入力
  • 承認:この承認者に属するユーザー名を入力。複数のユーザーを設定する場合、改行で区切って入力
  • 承認者:このグループに属する承認者ID(注:承認者のユーザー名ではありません)を改行で区切って入力。入力順番に制限はありません

グループ作成画面

設定状況の確認や内容の修正は、「ワークフロー」→「グループ一覧」から行えます。

グループ一覧

4.プラグインの詳細

新バージョンのWorkflowプラグインの詳細につきましては、下記のページからご確認いただけます。

Workflowプラグイン
プレビュー画面

Comments [0] | Trackbacks [0]

CからC++のクラスを利用する方法

July 12,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

CからC++のクラスを利用する方法を紹介します。

1.問題点

下記のC++プログラムを作りました。

foo.h

class Foo {
public:
    Foo();
    int abc(void);
};

foo.cc

#include "foo.h"
#include <iostream>
 
Foo::Foo() {}
 
int Foo::abc(void) {
    std::cout << "OK\n";
}

このC++プログラムをCのプログラムからアクセスしたいのですが、方法が分かりません。

ということで、CからC++のクラスを利用する方法を紹介します。

2.CからC++のクラスを利用する

やり方は色々あると思いますが、ここではC++プログラムにCからアクセスするためのラッパーを追加する方法を紹介します。

foo.h

#ifdef __cplusplus
extern "C" {
#endif
 
class Foo {
public:
    Foo();
    int abc(void);
};
 
void construct();
void execute();
void destruct();
 
#ifdef __cplusplus
}
#endif

ヘッダfoo.hには、ラッパー関数construct()、execute()、destruct()を宣言し、全体を「extern "C"」で括ります。「extern "C"」については「extern "C"の意味」をご覧ください。

foo.cc

#include "foo.h"
#include <iostream>
 
Foo::Foo() {}
 
int Foo::abc(void) {
    std::cout << "OK\n";
}
 
Foo *foo;
void construct() {
    foo = new Foo() ;
}
 
void execute() {
    foo->abc();
}
 
void destruct() {
    delete(foo);
}

foo.ccでは各ラッパー関数からクラスにアクセスするよう実装します。

Cのプログラム(test.c)は次のように書きます。

test.c

extern construct();
extern execute();
extern destruct();
 
int main() {
    construct();
    execute();
    destruct();
}

C++のラッパー関数はextern宣言します。

ビルドは、C++のコンパイルはg++、Cのコンパイルはgcc、リンケージはg++で行います。

% gcc -c test.c
% g++ -c foo.cc
% g++ -o a.out foo.o test.o

その他、上記のサンプルではラッパー内でnewを実施しないと実行時にセグメンテーションフォルトになったため、もしかしたらコンストラクタの実装が必要かもしれません。

Comments [0] | Trackbacks [0]

extern "C"の意味

July 4,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

extern "C"の意味について調べてみました。

1.はじめに

CプログラムからC++の関数を起動することを確認するため、下記のサンプルを作りました。

foo.h

class Foo {
private:
    int number;
public:
    Foo(int num);
    int print(void);
};
 
void construct();
void foo_print();
void destruct();

foo.cpp

#include "foo.h"
#include <iostream>
 
Foo::Foo(int num) {
    number = num;
}
 
int Foo::print(void) {
    std::cout << number << '\n';
}
 
Foo *foo;
void construct() {
    foo = new Foo(100) ;
}
 
void foo_print() {
    foo->print();
}
 
void destruct() {
    delete(foo);
}

test.c

extern foo_print();
extern construct();
extern destruct();
 
int main() {
    construct();
    foo_print();
    destruct();
}

このサンプルをビルドすると、リンケージで下記のエラーが発生します。

% gcc -c test.c
% g++ -c foo.cpp
% g++ -o a.out test.o foo.o
test.o: 関数 `main' 内:
test.c:(.text+0xa): `construct' に対する定義されていない参照です
test.c:(.text+0x14): `foo_print' に対する定義されていない参照です
test.c:(.text+0x1e): `destruct' に対する定義されていない参照です
collect2: エラー: ld はステータス 1 で終了しました

2.extern "C"の意味

リンケージエラーの説明の前に、サンプルコードfoo.cppをコンパイルのみ実行し、nmコマンドでシンボルリストを表示してみます。

% g++ -c foo.cpp
% nm foo.o
00000000000000db t _GLOBAL__sub_I__ZN3FooC2Ei
000000000000009e t _Z41__static_initialization_and_destruction_0ii
0000000000000089 T _Z8destructv
0000000000000043 T _Z9constructv
0000000000000074 T _Z9foo_printv
0000000000000008 b _ZL3foo
0000000000000016 T _ZN3Foo5printEv
0000000000000000 T _ZN3FooC1Ei
0000000000000000 T _ZN3FooC2Ei
                 U _ZNSolsEi
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
0000000000000000 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
                 U _ZdlPv
                 U _Znwm
                 U __cxa_atexit
                 U __dso_handle

次にfoo.hを下記のように「extern "C"」を付与してコンパイルし、nmコマンドでシンボルリストを表示してみます。

foo.h

#ifdef __cplusplus
extern "C" {
#endif
 
class Foo {
private:
    int number;
public:
    Foo(int num);
    int print(void);
};
 
void construct();
void foo_print();
void destruct();
 
#ifdef __cplusplus
}
#endif
% g++ -c foo.cpp
% nm foo.o
00000000000000db t _GLOBAL__sub_I__ZN3FooC2Ei
000000000000009e t _Z41__static_initialization_and_destruction_0ii
0000000000000008 b _ZL3foo
0000000000000016 T _ZN3Foo5printEv
0000000000000000 T _ZN3FooC1Ei
0000000000000000 T _ZN3FooC2Ei
                 U _ZNSolsEi
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
0000000000000000 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
                 U _ZdlPv
                 U _Znwm
                 U __cxa_atexit
                 U __dso_handle
0000000000000043 T construct
0000000000000089 T destruct
0000000000000074 T foo_print

2つのシンボルリストの違いは下記です。

extern "C"なし

0000000000000089 T _Z8destructv
0000000000000043 T _Z9constructv
0000000000000074 T _Z9foo_printv

extern "C"あり

0000000000000043 T construct
0000000000000089 T destruct
0000000000000074 T foo_print

extern "C"なしのシンボルは"_Z8"や"_Z9"という文字が追加されています。

これは「マングリング」と呼ばれ、C++では関数のオーバーロードや、複数のネームスペースに存在する同名の変数を見分けるようにするため、このようなマングリングを行う必要があるようです。

が、C言語にはマングリングという概念はありません。

test.cのオブジェクトファイルのシンボルは下記のようになっています。

% nm test.o
                 U construct
                 U destruct
                 U foo_print
0000000000000000 T main

つまり「extern "C"」なしでコンパイルを行うと、リンケージでCプログラムが期待するシンボル名construct/destruct/foo_printがみつからず、冒頭のリンケージエラーになってしまいます。

「extern "C"」ありでコンパイルを行うと、マングリングが不要なもの(ここではconstruct/destruct/foo_print)はマングリングされないため、Cプログラムとのリンケージが成功します。

Comments [0] | Trackbacks [0]

C++のコンストラクタで「no matching function for call to」というエラーになる場合の対処

June 28,2017 12:03 AM
Category:[C/C++]
Tag:[C++]
Permalink

C++のコンストラクタで「no matching function for call to」というエラーになる場合の対処について紹介します。

1.問題点

C++で下記の簡単なサンプルを作りました。

foo.h

class Foo {
private:
    int number;
public:
    Foo(int num);
    int print(void);
};

foo.cpp

#include "foo.h"
#include <iostream>
 
Foo::Foo(int num) {
    number = num;
}
 
int Foo::print(void) {
    std::cout << number << '\n';
}

test.cpp

#include "foo.h"
 
int main() {
    Foo f(100);
    f.print();
}

実行結果

% g++ foo.cpp test.cpp
% ./a.out
100

で、本題です。

上記のサンプルに、Fooクラスを継承するBarクラスを追加してみました。

bar.h

#include "foo.h"
 
class Bar: public Foo {
public:
    Bar(int num);
    int print(void);
};

bar.cpp

#include "bar.h"
#include <iostream>
 
Bar::Bar(int num) {
    number = num;
}
 
int Bar::print(void) {
    std::cout << number << '\n';
}

foo.hのメンバ変数numberは子クラスからもアクセスするのでprivateからprotectedに変更。

foo.h

class Foo {
protected:
    int number;
public:
    Foo(int num);
    int print(void);
};

test.cppからのインクルードやmain()のクラス型はFooからBarにそれぞれ変更します。

test.cpp

#include "bar.h"
 
int main() {
    Bar f(100);
    f.print();
}

ビルドを実行すると、コンパイルで「no matching function for call to 'Foo::Foo()'」というエラーが発生します。

% g++ foo.cpp bar.cpp test.cpp
bar.cpp: コンストラクタ 'Bar::Bar(int)' 内:
bar.cpp:4:17: エラー: no matching function for call to 'Foo::Foo()'
Bar::Bar(int num) {
^

2.原因

コンパイルエラーの原因はつぎのいずれかになります。

  • Fooクラスに引数が空のコンストラクタが定義されていない
  • Barクラスのコンストラクタに継承するコンストラクタが定義されていない

ひとつめの原因の解説ですが、C++の子クラスでコンストラクタを起動すると、先に親のコンストラクタが呼ばれるようになっています。

前述のBarクラスのコンストラクタ定義では、Barのコンストラクタ起動前に、親クラスの引数なしのコンストラクタが起動されるのですが、Fooクラスには引数なしのコンストラクタが定義されていないため、「no matching function for call to 'Foo::Foo()'(Foo::Foo()の関数呼び出しが正常に行えない)」というエラーに遭遇してしまったようです。

あるいはBarクラスのコンストラクタを変更して、継承する親コンストラクタを定義すれば、親クラスに引数なしのコンストラクタを定義する必要はありません。

ということで、それぞれの原因に対する対処方法を下記に示します。

ちなみにC++にはJava言語の「super」に該当するものはありません。

3.対処方法1:Fooクラスに引数が空のコンストラクタを定義

ひとつめの対処方法は、赤字で示すように、Fooクラスに引数が空のコンストラクタを定義することです。

foo.h

class Foo {
protected:
    int number;
public:
    Foo();
    Foo(int num);
    int print(void);
};

foo.cpp

#include "foo.h"
#include <iostream>
 
Foo::Foo() {}
 
Foo::Foo(int num) {
    number = num;
}
 
int Foo::print(void) {
    std::cout << number << '\n';
}

実行結果

% g++ foo.cpp bar.cpp test.cpp
% ./a.out
100

4.対処方法2:Barクラスのコンストラクタに継承するコンストラクタを定義

もうひとつの対処方法は、Barクラスのコンストラクタ定義に、赤字で示すように継承するコンストラクタを定義することです。

bar.cpp

#include "bar.h"
#include <iostream>
 
Bar::Bar(int num): Foo(num) {
    number = num;
}
 
int Bar::print(void) {
    std::cout << number << '\n';
}

実行結果

% g++ foo.cpp bar.cpp test.cpp
% ./a.out
100

継承するコンストラクタのパラメータは変数名のみ記述すればOKです。型の記述は必要ありません。

Comments [0] | Trackbacks [0]

Windows+Chromeで「この接続ではプライバシーが保護されません」となる場合の対処

June 21,2017 12:03 AM
Category:[Google Chrome]
Tag:[GoogleChrome]
Permalink

Windows+Chromeで「この接続ではプライバシーが保護されません」となる場合の対処方法について紹介します。

1.問題点

Google ChromeであるSSLなページを開くと「この接続ではプライバシーが保護されません」となる場合」があります。

が、対処方法が分かりません。

ということで、「この接続ではプライバシーが保護されません」となる場合の対処について紹介します。

ここではWindowsの対処方法になります。

2.対処方法1

IEを開き、ツールアイコンをクリックして「インターネットオプション」をクリック。

「詳細設定」タブをクリック。

SSLおよびTLS関連の項目をすべてチェックして「OK」をクリック。

これで冒頭のメッセージが表示されなくなり、正常に接続できるようになる可能性があります。

3.対処方法2

Chromeのアドレスバーに下記を入力。

chrome://net-internals/#hsts

「Delete domain」にドメインを入力して「Delete」をクリック(実行しても画面に変化はありません)。

これでエラーが発生したページを再読み込みすれば、正常に接続できるようになる可能性があります。

4.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

shmgetの"0x1b6"の意味

June 16,2017 12:03 AM
Category:[Linux]
Tag:[Linux]
Permalink

shmgetの"0x1b6"の意味について調べてみました。

1.はじめに

Linuxには、共有メモリーセグメントを割り当てるshmget()というシステムコールがあります。

shmid = shmget(key, sizeof(pthread_mutex_t), IPC_CREAT | IPC_EXCL | 0x1b6);

こういうサンプルをみかけるのですが、第3パラメータにある"0x1b6"の意味が分かりません。

ということで、shmgetの"0x1b6"の意味について調べてみました。

2."0x1b6"の意味

manコマンドによると、shmgetの第3パラメータはshmflgといい、動作を決めるための各フラグを設定します。

上記のサンプルにある、IPC_CREATとIPC_EXCLの意味は次のとおりです。

IPC_CREAT

新しいセグメントを作成する。このフラグが指定されなかった場合、 shmget() は key に対応するセグメントを探し、 ユーザーがそのセグメントにアクセスする許可があるかどうかをチェックする。

IPC_EXCL

このフラグは IPC_CREAT とともに使用し、 この呼び出しで確実にセグメントが作成されるようにする。 セグメントが既に存在した場合には、 呼び出しは失敗する。

この2つの値はOR条件で組み合わせられます。ちなみに16進数表記の値はそれぞれ下記のとおりです。

  • IPC_CREAT:0x200
  • IPC_EXCL:0x400

manの説明は、次のように続いています。

上記のフラグに加えて、 shmflg の下位 9 ビットは、所有者、グループ、その他への許可を指定する。 これらのビットは open(2) の mode 引き数と同じ形式で同じ意味を持つ。 今のところ、システムは実行 (execute) 許可を参照しない。

「下位 9 ビット」がどうやら"0x1b6"を指すようです。

"0x1b6"を2進数に分解すると、0001 1011 0110になります(下位9bitなので上位3bitの"000"は無視)。

下位9bitを3ビットずつ区切ると、110 110 110になります。

10進数に直すと「666」になり、これでパーミッションの指定を行っているようです。

つまり"0x1b6"は「666」というパーミッションの設定を行っているということですね。

Comments [0] | Trackbacks [0]

C++のクラス変数にstaticにして「~に対する定義されていない参照です」というエラーになる場合の対処

June 15,2017 12:03 AM
Category:[C/C++]
Tag:[C++]
Permalink

C++のクラス変数にstaticにして、「~に対する定義されていない参照です」というエラーになる場合の対処について紹介します。

1.問題点

下記のサンプルを作りました。

このサンプルのポイントは、クラス変数fooをstaticで定義している点です。

sample.h

class Sample {
private:
    int foo;
public:
    Sample(int number);
    void display();
};

sample.cpp

#include <iostream>
#include "sample.h"
 
Sample::Sample(int number) {
    foo = number;
}
void Sample::display() {
    std::cout << foo << std::endl;
}

test.cpp

#include "sample.h"
 
int main() {
    Sample test(100);
    test.display();
    return 0;
}

実行結果

% g++ sample.cpp test.cpp
% ./a.out
100

次に、クラス変数fooをstaticに変更してみます。staticを付与することで、メンバ変数は実体が1つだけになります。

sample.h

class Sample {
private:
    static int foo;
public:
    Sample(int number);
    void display();
};

このサンプルをコンパイルすると、リンケージで下記のエラーが発生します。

% g++ sample.cpp test.cpp
/tmp/ccFBFNh2.o: 関数 `Sample::Sample(int)' 内:
sample.cpp:(.text+0x10): `Sample::foo' に対する定義されていない参照です
/tmp/ccFBFNh2.o: 関数 `Sample::display()' 内:
sample.cpp:(.text+0x24): `Sample::foo' に対する定義されていない参照です
collect2: エラー: ld はステータス 1 で終了しました

クラス変数fooの定義がされていないというエラーのようですが、対処方法が分かりません。

ということで、「~に対する定義されていない参照です」というエラーになる場合の対処について紹介します。

2.原因と対処

原因はエラーメッセージのとおりです。

対処方法は、sample.cppに赤色で示したクラス変数の定義を追加します。

#include <iostream>
#include "sample.h"
 
int Sample::foo;
 
Sample::Sample(int number) {
    foo = number;
}
void Sample::display() {
    std::cout << foo << std::endl;
}

これで正常にコンパイルが完了します。

実行結果

% g++ sample.cpp test.cpp
% ./a.out
100
Comments [0] | Trackbacks [0]

Finaleで曲の途中で二段譜から一段譜に変更する方法

June 11,2017 12:03 AM
Category:[Finale]
Tag:[Finale]
Permalink

Finaleで曲の途中で二段譜から一段譜に変更する方法を紹介します。

変更前
変更前

変更後
変更後

1.はじめに

Finaleでパート譜を作りました。

パートが上下で分かれているため2段で表示されるのですが、片方のパートの休符が多いところは1段で表示したいのですが、設定方法が分かりません。

ということで、曲の途中で二段譜から一段譜に変更する方法を紹介します。

2.曲の途中で二段譜から一段譜に変更する

曲の途中で二段譜から一段譜に変更するには、「五線ツール」のアイコンをクリック。

五線ツール

変更したい小節を選択して右クリック。

(クリックで拡大)
変更したい小節を選択

「五線」→「空の五線を隠す」をクリック。

空の五線を隠す

これで休符の小節が非表示になりました。

(クリックで拡大)
休符の小節が非表示

Comments [0] | Trackbacks [0]

ネットで郵便転送を依頼する方法

June 9,2017 12:03 AM
Category:[その他]
Tag:[Service]
Permalink

ネットで郵便転送を依頼する方法を紹介します。

1.はじめに

郵便転送を依頼することになりました。

以前であれば郵便局に行って転送依頼の手続きをしていたのですが、調べたところ、ネットで郵便転送を依頼できることが分かりました。

ということで、ネットで郵便転送を依頼する方法を紹介します。

2.郵便転送を依頼する

e転居のページにアクセスして、PCの場合は「e転居のお申込みはこちらから」、スマホの場合は「スマートフォンご利用の方はこちらから」をクリック。ここではPCの場合で説明を進めます。

e転居のページ

利用確認画面が表示されるので「同意する」をチェックして「次へ進む」をクリック。

(クリックで拡大、以下同様)
利用確認画面

氏名・フリガナ・メールアドレスを入力して「次へ進む」をクリック。

メールアドレス入力画面

表示された氏名・フリガナ・メールアドレスを確認し、問題なければ「次へ進む」をクリック。

メールアドレス確認画面

登録したメールアドレスに確認メールが送信されるので、メールに記載されたURLにアクセス。

確認メール画面

旧住所・新住所を入力して「次へ進む」をクリック。

住所情報入力画面

表示された住所情報を確認し、問題なければ「次へ進む」をクリック。

住所情報入力画面

転居する人の氏名と旧住所に残る人数、転送開始日を入力して「次へ進む」をクリック。

転居者情報入力画面

表示された転居者と旧住所に残る人数、転送開始日を確認し、問題なければ「次へ進む」をクリック。

転居者情報確認画面

登録した電話番号から表示された番号に電話し、自動音声にしたがって画面に表示されている「確認番号(6ケタ)を入力します。自動音声が正常に終了したら画面下にある「申請登録」をクリック。

届出者確認入力画面

これで転送の申請完了です。

受付完了画面

Comments [0] | Trackbacks [0]

C/C++で16進数の文字列を16進数の整数に変換する方法

June 6,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C/C++で16進数の文字列を16進数の整数に変換する方法を紹介します。

1.問題点

下記の、16進数を変数に代入し、それをさらに別の変数に代入して表示するプログラムを作りました。

#include <stdio.h>
 
int main(int argc, char *argv[]) {
    int data, result;
    data = 0x0a; // 16進数
    result = data;
    printf("data:%#.2x(%d)\n", result, result);
    return 0;
}

実行結果

% ./a.out
data:0x0a(10)

プログラムの中で16進数を代入した場合、期待通りに代入および表示することができますが、引数で16進数を受け取った場合、文字列として扱われるため、プログラム内で整数に変換する方法が分かりません。

2.16進数の文字列を16進数の整数に変換する

16進数の文字列を16進数の整数に変換するにはsscanf()を利用します。

#include <stdio.h>
 
int main(int argc, char *argv[]) {
    int data, result;
    sscanf(argv[1], "%x", &data);
    result = data;
    printf("argv[1]:%s => data:%#.2x(%d)\n", argv[1], result, result);
    return 0;
}

実行結果(第1パラメータに16進数指定)

% ./a.out 0x0a
data:0x0a(10)

sscanf()は、第1パラメータで示す文字列ポインタからの入力を読み込み、第2パラメータのフォーマットで第3パラメータ以降の変数に代入する関数です。

第3パラメータ以降はアドレス指定でなくてはいけません。

Comments [0] | Trackbacks [0]
 1  |  2  |  3  |  4  |  5  | All pages