amazon

30.4.11

warning C4793: `anonymous namespace'::CV_XADD': ネイティブ関数としてコンパイルされました

c:\program files\opencv-2.2.0\modules\core\include\opencv2\core\operations.hpp(81): warning C4793: `anonymous namespace'::CV_XADD': ネイティブ関数としてコンパイルされました:
1> インラインのネイティブ アセンブリはマネージ コードでサポートされていません
という警告を消すには、
stadfx.hの中に、operations.hppを呼び出しているファイルのヘッダーを書き加え、#pragma unmanagedと#pragma managedで括ればよい。
つまり、
// stdafx.h
#pragma once

#pragma unmanaged
#include "foo.h"
#pragma managed
警告の通り、マネージコードにしなければよい。

28.4.11

プロシージャエントリポイント_ftol2がダイナミックリンクライブラリmsvcrt.dllから見つかりませんでした

OpenGLで作成したプログラムをWindows XP で起動すると、
プロシージャエントリポイント_ftol2がダイナミックリンクライブラリmsvcrt.dllから見つかりませんでした
と出た。

作成は、OS: Windows 7で、Visual Studio 2010 のC++である。

この原因は、Windows 7付属のOPENGL32.dllをアプリケーションフォルダにコピーしたことにある。
アプリケーションフォルダに、Windows 7の OPENGL32.dllがあるとそれを読み込んでしまいエラーが起こる。
本来はc:¥Windows¥system32¥にあるWindos XP付属のOPENGL32.DLLを読み込む必要がある。
よって、アプリケーションフォルダのOPENGL32.dllを削除すれば良い。

error: jump to case label error: crosses initialization of ‘******’



error: jump to case label
error: crosses initialization of ‘******’
がswitch文で出る。
case 1:
[some functions]
break;
を下に変えればよい。
case 1:{
[some functions]
break;
}

26.4.11

std::vector の初期化時メモ


std::vector<std::string> array(10);
などとし、
array.push_back("blah-blah");
とすると、"blah-blah"は11番目の要素に代入される。
つまり、
for(int i = 0; i < array.size(); i++ ) std::cout << array[i] << "," << std::endl;
は、
,,,,,,,,,,blah-blah,
となる。

24.4.11

error LNK2001 in Visual Studio 2010 with OpenCV

error LNK2001: 外部シンボル ""public: virtual void __thiscall cv::HOGDescriptor::setSVMDetector(class std::vector<float,class std::allocator<float$gt; $gt; const &)" (?setSVMDetector@HOGDescriptor@cv@@UAEXABV?$vector@MV?$allocator@M@std@@@std@@@Z)" は未解決です。
リンカーのエラーによるもの。
プロパティ - リンカー - 入力 -追加の依存ファイル
This is an error of Linker.
Property - Linker - Input - Additional Dependencies

ここで、Add
C:\Program Files\OpenCV-2.2.0\build\lib\Debug\opencv_objdetect220d.lib
C:\Program Files\OpenCV-2.2.0\build\lib\Release\opencv_objdetect220.lib

error C2855 in Visual Studio 2010

error C2855: コマンド ライン オプション '/clr' は、プリコンパイル済みヘッダーが作成されたときのものと異なります。
該当するファイルのプロパティで、
プリコンパイル済みヘッダーを変更する
使用(/Yu) -> 作成(/Yc)

23.4.11

C++ string <-> double, int 等の変換 (2)

先日のものは、doubleからstringにするときに桁数が落ちていたので、
精度を落とさずに変換する方法を記す。

#include <string>
#include <sstream>
#include <iomanip> //追加

std::string double2string(double d){
std::string rt;
std::ostringstream oss;
oss << std::setprecision(16) << d; //精度を指定
rt.assign(oss.str(),0,15); //桁数を指定
return rt;
}

22.4.11

C++ string <-> double, int 等の変換

文字列string から数字 double, int 等の変換は
sstreamを使うことで案外簡単にできることが分かった。

#include <string>
#include <sstream>

double string2double(const std::string& str){
double rt;
std::stringstream ss;
ss << str;
ss >> rt;
return rt;
}

std::string double2string(double d){
std::string rt;
std::stringstream ss;
ss << d;
ss >> rt;
return rt;
}
こんな感じ。

warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます

Visual Studio 2010 C++ で
「warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。」
と出た。

コメントで日本語を使っていたのが問題だった。

warning C4067: プリプロセッサ ディレクティブの後に余分な文字がありました

Visual Studio 2010 C++ で
「warning C4067: プリプロセッサ ディレクティブの後に余分な文字がありました - 改行が必要です」
と出た。

プリプロセッサで
#ifdef __APPLE__ || WIN32
としていたのが問題。

#if defined(__APPLE__) || define(WIN32)
とするがよろし。

20.4.11

Snow Leopard に、Mac Portsでatlasをインストール


Macportsでatlasをインストールするときに、building atlas で止まってしまう現象について。
6時間待ったらインストールできたとあったので、やってみた。
$ sudo port clean atlas
$ sudo port install atlas
一旦、atlasをクリーンしてから、再度インストールをしたところ、
やっぱり6時間くらいでインストールが完了できた。
インストールされたバージョンは @3.9.37_0

18.4.11

Windows 7 on Parallels インストール時の文字化け

インストーラが文字化けするときの対処が、RUNEXYのホームページに載っている。
概要は以下のとおり。

「コントロールパネル」-「地域と言語」-

「形式」タブの[形式]

「場所」タブの[現在の場所]

「管理」タブの[Unicode対応でないプログラムの現在の言語] -「現在のシステムロケール」

を日本語にする。

ALUT + OpenALで音が出ない


Xcodeで、frameworkとstatic libraryとdynamic libraryを作る方法。alutの例。
で、コンパイルしたライブラリだが、インクルード指定の順番が重要であることが分かった。

$gcc main.cpp -lalut -framework OpenAL
または
$gcc main.cpp -framework ALUT -framework OpenAL
は、コンパイルが通り音が出る。

$gcc main.cpp -framework OpenAL -lalut
または
$gcc main.cpp -framework OpenAL -framework ALUT
これだと、音が出ない。

-framework ALUTも-lalutも中身は同様であるから、
ALUTをOpenALより前に持って来ないといけないらしい。

Visual Studio 2010 on Parallels Desktop 6 on Snow Leopard

Snow Leopard上で動かした、Parallelsで走らせたVisual Studio 2010で、
複雑なソリューションをビルドすると、Visual Studioがフリーズしたようになり、
ビルドをキャンセルすると、
Error MSB4014がでる問題について。

Microsoft Connectにもあるように、
ParallelsのCPUを2つ使うように設定したらフリーズしなくなったようだ。

So, for Error MSB4014 in Visual Studio 2010 on Parallels Desktop 6 on Snow Leopard,
using 2 cores of CPUs in Parallels may solve the problem.

17.4.11

Xcodeで、frameworkとstatic libraryとdynamic libraryを作る方法。alutの例。


ソースを取ってきてコンパイルしてライブラリを作成する場合、
$./configure -[オプション]
$make
$sudo make install
などとコンパイルする方法が用意されているが、frameworkや32bit用または64bit用スタティックライブラリ、ダイナミックライブラリを作成したい時にはXcodeでコンパイルすると楽。
付属のMakefileでコンパイルするとSnow Leopardだと自動的に64bitになるから厄介。

今回は、OpenALのalutライブラリ作成を例に行う。

まずは、frameworkの作成。
これはメモてきなあれと,日記てきなあれ.さん、参照。
これで、をインクルードしたmain.cppが
$g++ -m32 main.cpp -framework OpenAL -framework ALUT
でも、
$g++ -m64 main.cpp -framework OpenAL -framework ALUT
でも、コンパイルが通るはず。

static library, dynamic library作成は、上と同様にして、
Xcodeのプロジェクトで、BSD C Libraryをstaticまたはdynamicにして
32bitならi386、64bitならx86_64を指定してリリースをビルド。
出来上がった、
libalut.a、libalut.dylibを
/usr/local/lib/
に移動すればよい。
これで、
$g++ -m32 main.cpp -framework OpenAL -lalut
と、
$g++ -m64 main.cpp -framework OpenAL -lalut
でコンパイルが通るようになる。

シリアルポート送信とその注意


CまたはC++でtermiosを使ってシリアル送信を試みた。
クラスを用いてオブジェクトを作ってみた。
始めうまく行かなかった原因が分かったのでメモ。

マシンはmacだが、シリアル接続に使っているのはELECOM製UC-SGT。これでUSB to シリアルケーブルしている。
UC-SGTには、macのドライバが付属していないが、別途使えるようにする方法があるので、mac UC-SGTなどとぐぐってみるとよい。

シリアル送受信の接続確認は
windowsだとTeratermなどが簡単だが、
macならターミナルでscreenかcuを使うとよい。

screenは林檎生活100さんのサイトを参照した。

接続する際のportのパスは、
/dev/cu.usbserial
または
/dev/tty.usbserial
僕の場合はどちらで接続できた。

ここから本題。
稚拙だがC++で接続するプログラムを書いてみた。

termiosの設定については、
FreeBSD 日本語マニュアル検索 (jman/japropos/jwhatis)

termios(4) Mac OS X Manual Page
を参照。

//serialsend.h
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>

#define BAUDRATE B9600
#define PORT "/dev/cu.usbserial"

class SerialPort{
private:
int fd;
struct termios oldtio,newtio;
public:
SerialPort();
int open(const char*);
int send(const char*, int);
void close(void);
};

//serialsend.cpp
/*シリアルポートに信号を送るプログラム*/
#include "serialsend.h"

SerialPort::SerialPort(){ //コンストラクタ
memset(&newtio, 0, sizeof(newtio));//ポート設定の初期化

cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);

newtio.c_iflag |= IGNPAR;

newtio.c_oflag |= OPOST;
newtio.c_oflag &= ~ONLCR;

newtio.c_cflag |= CS8;
newtio.c_cflag |= CSIZE;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag |= CREAD;
newtio.c_cflag &= ~PARENB;
newtio.c_cflag &= ~PARODD;
newtio.c_cflag |= HUPCL;
newtio.c_cflag |= CLOCAL;

newtio.c_lflag |= ICANON;

newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
}

int SerialPort::open(const char* port){
//モデムデバイスを開く
fd = ::open(port, O_RDWR | O_NOCTTY | O_NDELAY);

//モデムデバイスが開けたかチェック
if(fd<0){
std::cerr<<"Error! "<<port<<" can not be opend."<<std::endl;
return -1;
}else{
fcntl(fd, F_SETFL, 0);
std::cout<<"Serial port fd="<<port<<" was opened."<<std::endl;
}

tcgetattr(fd,&oldtio); // 現在のポート設定を待避
tcflush(fd, TCIOFLUSH); //受信したが読み込んでいないデータ、および書き込んだが送信していないデータの両方を消去
tcsetattr(fd,TCSANOW,&newtio);
send("Port initiated. ",16); //ポートの初期化に一度何かを送っておくと調子がよさそう
return fd;
}

int SerialPort::send(const char* buf, int size){
int rt = write(fd, buf, size);

if(rt == size) {
std::cout<<buf[0]<<"... was sent."<<std::endl;
}else if(rt < 0){
std::cerr<<"Error! "<<buf[0]<<"... was not sent."<<std::endl;
}else{
std::cerr<<"Error! "<<buf[0]<<"... was partially sent."<<std::endl;
}

usleep(20000); //送信完了までの待ち時間

return rt;
}

void SerialPort::close(void){
tcsetattr(fd,TCSANOW,&oldtio);
::close(fd);
}

//main.cpp
#include "serial_send.h"

int main(void){
SerialPort a;
a.open(PORT);
a.send("something",9);
a.close();
return 0;
}

正しく送信するには、赤字の行が必須のようである。
試しにその行をコメントアウトすると、送信できないか、送信はできるが文字化けした。
usleep(20000)は20 msであるが、10 msだとほどんどの場合文字化けが起こり送信が正しく行われなかった。

シリアルポートではもっと細かい時間制御はできないのであろうか。
理論上1µsくらいまでいけそうだと思うのだが。
とにかく、上のプログラムでデータ送信を行う場合は処理に20 ms以上かかることを考慮に入れて設計をしなければならない。

12.4.11

C++ std::vectorのメソッドinsertでの注意


<メモ>
insertするとイテレータが無効になる

std::vector<std::string> vec;
vec.push_back("文字列1");
vec.push_back("文字列2");
vec.push_back("文字列3");
と作ったvectorオブジェクトvec = 文字列1, 文字列2, 文字列3(この順になっている)
の3要素目に文字列4を挿入して、vec = 文字列1, 文字列2, 文字列4, 文字列3 としたい。

std::vector<std::string>::iterator it = vec.begin(); //イテレータの初期化 この時点でitには文字列1の先頭アドレスが入る
for (int i = 0; i < 2; i++) ++it; //イテレータを2つ進める itには文字列3の先頭アドレス
vec.insert(it , "文字列4"); //文字列4の挿入
これで完成。
で、ここでこの後に
++it;
vec.insert(it , "文字列5");
とやると、4要素目には挿入できない。

4.4.11

char型の配列番号が変わってしまう現象


キーボード入力した一文字を取得して、char型配列に格納するプログラムを作っていたのだが、
変数ではなく配列の要素番号が変わってしまう現象が起きた。

#include <iostream>

class Obj{
  private:
    char c[10];
    int i;
  public:
    Obj(void);
    void func(void);
};

Obj::Obj(){
   i = 0;
}

void Obj::func(void){
   std::cout<<"i = "<<i<<std::endl;
   c[i] = 'a';
   std::cout<<"i = "<<i<<std::endl;
}

int main (void ){
   Obj obj;
   obj.func();
   return 0;
}
これを実行すると
$ ./a.out
i = 0
i = 97
となる。
i はいじってないのにと、思ったが、
原因は、char c[]の部分。
これをちゃんとchar c[10]とかにしておけば、よし。