VC++からデータベースに接続し、取得できたデータをフォームに出力するには?

解決


トマト  2009-09-02 00:20:59  No: 70845

ボタンを押下されたら、データベースにアクセスして取得できた情報を
例えば、テーブル「aaa」の内容がメッセージボックスで表示する方法で

Win32 コンソールアプリケーション  =>データベースアクセス
Win  フォームアプリケーション     =>ボタン押下された時のフォームの状態遷移

結合といいますか、フォームからコンソールを呼ぶ?
データベースの情報を取得するにはどういった処理内容をしたらいいのでしょうか?
ご教授をお願いいたします!

http://park1.wakwak.com/~ima/visualcpp_pgsql2.html
を参考に勉強をしているのですが、今回は別々に作成してしまったので
どうにか取り込めないかご教授願えないでしょうか?

環境は
Visual Stadio 2008  です


επιστημη  URL  2009-09-02 17:43:21  No: 70846

コンソールアプリケーション側が結果を標準出力に
出してくれるなら、_popen が使えそう。


maru  2009-09-02 20:14:49  No: 70847

> コンソールアプリケーション側が結果を標準出力に
> 出してくれるなら、_popen が使えそう。
そんな関数が有るんですね。

でもMSDNによると

メモ :  
_popen 関数を Windows プログラムで使用すると無効なファイル ポインタを返すため、プログラムが無期限に応答を停止する原因になります。_popen は、コンソール アプリケーションでは正しく動作します。入出力をリダイレクトする Windows アプリケーションの作成方法については、Windows SDK の「Creating a Child Process with Redirected Input and Output」を参照してください。

だそうです。
http://msdn.microsoft.com/ja-jp/library/96ayss4b.aspx


επιστημη  URL  2009-09-02 20:22:59  No: 70848

...だそうです ^^;

てか、コンソールアプリからDBアクセスやってるとこ引っこ抜いて
Winフォームアプリに持ち込んじゃダメなんだろか。
あるいはライブラリに仕立てちゃダメなんだろか。
"わざわざ"メンドクセーことしてない?


subaru  2009-09-02 21:40:47  No: 70849

コンソールの出力の取得であれば CreatePipe で作成したパイプを
CreateProcess に渡して結果を読み出す方法もあります。

EXEを分けないならフォームアプリケーションから
DBアクセス部分を直接使えばいいだけですね。


subaru  2009-09-02 21:51:50  No: 70850

>コンソールの出力の取得であれば CreatePipe で作成したパイプを
>CreateProcess に渡して結果を読み出す方法もあります。

って、maruさんのリンク先にも書かれてましたね(^^;


maru  2009-09-02 22:33:32  No: 70851

επιστημηさんの意見に賛成!

EXEのまま、DBアクセス部分をexportするってのもあるかも。
# たしかEXE内の関数も呼び出しできると思ったけど、最近確認していないから実際にできるかどうかは知らない。


トマト  2009-09-03 00:36:17  No: 70852

>EXEのまま、DBアクセス部分をexportするってのもあるかも。
この方法があるなら是非、やってみたいです!!

今は、επιστημηさんの意見
>コンソールアプリからDBアクセスやってるとこ引っこ抜いて
>Winフォームアプリに持ち込んじゃダメなんだろか。
ってのをやっているのですが
libpq.dllのリンクに失敗してハマってます。
DBにアクセスする際の作ってたコンソールアプリのファイル
依存関係も同じにしてみたりしたのですがなかなか抜け出せてません(T_T)

今度は、subaruさんの
CreatePipe,CreateProcessを使用したものを使ってみようかと思っています
まずは、「CreatePipeって何?」って所からですが....


トマト  2009-09-03 00:45:56  No: 70853

訂正)  一応,,,
libpq.dll-> libpq.libでした。すみません


επιστημη  URL  2009-09-03 17:41:03  No: 70854

> libpq.dllのリンクに失敗してハマってます。

ソコくわしく。
そんだけじゃなんもわからん。


トマト  2009-09-03 19:51:44  No: 70855

//ボタン押下されたときの処理に
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {

    const char *conninfo;
    PGconn     *conn;
    PGresult   *res;
    int         nFields;
    int         i,
                j;
    //** localhostの"postgres"というDBを予め作成しておく
  conninfo = "host=localhost dbname=postgres user=postgres password=postgres";
    
    /* データベースとの接続を確立する */
    conn = PQconnectdb(conninfo);

と書き込んで、
フォームアプリのプロジェクト(access)のプロパティ
[構成のプロパティ]−[リンカ]-[入力]-[追加の依存ファイル]にlibpq.lib
と記入。
[ツール]-[オプション]-[プロジェクト及びソリューション]-[VC++ディレクトリ]の中にある実行可能ファイルに
\\D:\PostgreSQL\8.4を環境構築にて$(PATH)を記入

C:\Documents and Settings\test\My Documents\Visual Studio 2008\Projects\access\Debug\
の下にlibpq.dllとかlibpqdll.lib他(.dll)を10個くらい置いてます

コンソールアプリでデータベースにアクセスできているのを確認して
そこで使われていた(.dll)を全部コピペしてみました

自分で分かるのはこれくらいで
他にやっておかなければ行けない事はありますでしょうか?


επιστημη  URL  2009-09-03 20:22:06  No: 70856

そしたらどうなっちゃったの?
なにがどのように失敗したの?
コンパイルエラー? リンクエラー? 実行時エラー?
さっぱりわからんよ。


トマト  2009-09-03 21:47:39  No: 70857

エラーがいっぱいでていて(一例だけ抜粋)以下のような物が・・・
1>リンクしています...
1>access.obj : error LNK2031: "extern "C" void __clrcall PQfinish(struct pg_conn *)" (?PQfinish@@$$J0YMXPAUpg_conn@@@Z) の p/invoke を生成できませんでした。呼び出し規約がメタデータに見つかりません。
1>dbaccess.obj : warning LNK4248: 未解決の typeref トークン (01000022) ('pg_conn') です。イメージを実行できません。
1>dbaccess.obj : error LNK2028: 未解決のトークン (0A000015) "extern "C" void __clrcall PQfinish(struct pg_conn *)" (?PQfinish@@$$J0YMXPAUpg_conn@@@Z) が関数 "private: void __clrcall dbaccess::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@dbaccess@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z) で参照されました。
1>C:\Documents and Settings\suzuki\My Documents\Visual Studio 2008\Projects\access\Debug\access.exe : fatal error LNK1120: 外部参照 14 が未解決です。

何を言われているのか良く理解できてなくて申し訳ないのですが
>なにがどのように失敗したの?
>コンパイルエラー? リンクエラー? 実行時エラー?
-->リンクエラー?ですかね。

1>コンパイルしています...
1>access.cpp
1>リンクしています...
1>access.obj : error LNK2031: "extern "C" void __clrcall…
になっていたので、コンパイルエラーは切り抜けているかと

.exeも出来上がっていなかったので実行時エラーではないかも?


タイロン  2009-09-04 02:40:04  No: 70858

[構成のプロパティ]−[リンカ]-[全般]-[追加のライブラリ ディレクトリ]を確認してください。
あなたのおっしゃる「libpq.lib」が入っているディレクトリ
「C:\Documents and Settings\test\My Documents\Visual Studio 2008\Projects\access\Debug\
」へのパスが入っていないのではないでしょうか。


タイロン  2009-09-04 02:40:04  No: 70859

[構成のプロパティ]−[リンカ]-[全般]-[追加のライブラリ ディレクトリ]を確認してください。
あなたのおっしゃる「libpq.lib」が入っているディレクトリ
「C:\Documents and Settings\test\My Documents\Visual Studio 2008\Projects\access\Debug\
」へのパスが入っていないのではないでしょうか。


タイロン  2009-09-04 02:56:37  No: 70860

すいません。
[プロジェクト]→[プロパティ]→[構成プロパティ]→[全般]→[共通言語ランタイムサポート]が/clr:pureになってませんか?/clrに変更すれば、LNK2031エラーについては解決すると思います

ご参考:http://msdn.microsoft.com/ja-jp/library/ms173734.aspx

困ったことがあれば、エラーコードでGoogle検索すると似たような事例が見つかることがありますよ!


トマト  2009-09-04 04:02:10  No: 70861

タイロン様  ありがとうございました!
リンクエラーが解決しました!
-------------------------------------------------------------
>[追加のライブラリ ディレクトリ]
>[共通言語ランタイムサポート]が/clr:pure
[追加のライブラリ ディレクトリ]が無記入になっており、また[共通言語ランタイムサポート]がご指摘とおり 「/clr:pure」になってました。
------------------------------------------------------------

現在はデバック中にエラーでDBにアクセスしてくれません
([Form1]にbuttumをひとつ作成して、ボタンを押下されるとデータベースにアクセスするようになっています)
ボタンを押下すると、メッセージボックスが表示され(エラー表示)
アプリケーションのコンポーネントでハンドルされていない例外が発生しました。「続行」をクリックすると…
保護されているメモリに読書き操作を行おうとしました…

のようになってしまいました。
どうしたら解決するのか検討もつかないのでいろいろgoogleで探してみます


トマト  2009-09-05 00:38:12  No: 70862

あいまいな表現で申し訳ありませんでした。
申し訳ありませんが、もう少しご教授ください
-----------------------------------
readData(unsigned long data); //DBアクセス
------------------------------------
テキストボックスに入っている数字(System::String)を取得して
unshigned longに変換する

char str[] = "this->textBox1->Text";

String^ s = gcnew String( str );
char *endptr;
unsigned long ul;
ul = strtoul(str, &endptr, 10);
readData(ul);
         MessageBox::Show(this->textBox1->Text);

それで、上記のようなデバックエラーになってしまうのですが
キャストの仕方が間違っているのでしょうか?


επιστημη  URL  2009-09-05 00:42:52  No: 70863

> テキストボックスに入っている数字(System::String)を取得して
> unshigned longに変換する

どう見ても "this->textBox1->Text" を数値に変換
(当然失敗)してるようにしか思えないのですけど。


Blue  2009-09-05 00:46:49  No: 70864

>デバックエラー
とは?
(デバッグですし)

>char str[] = "this->textBox1->Text";
何をしたいのでしょうか?これだと、

this->textBox1->Text

という文字列になりますよ。(this->textBox1->Textの値ではない)

int i = 10;
char str[] = "i";

と同じ。

>ul = strtoul(str, &endptr, 10);
this->textBox1->Textの値を数値で取りたいのであれば、UInt32::TryParseあたりで変換してください。
ちゃんとエラー処理できますし。
# unsigned long は  UInt32でよかったけ?


みい  2009-09-05 00:48:43  No: 70865

> ul = strtoul(str, &endptr, 10);
これは何をやりたいのでしょうか??
strtoulって数値の入った文字列を数値に変換する関数なんですけど
(数値以外の文字が入ったらその文字の前までを変換)。
例) "10sec"→10


επιστημη  URL  2009-09-05 01:29:11  No: 70866

ま、↓こんなトコすかね。

using namespace System;

int main() {
  String^ str = L"123"; // 変換対象文字列
  UInt32 val;
  if ( UInt32::TryParse(str,val) ) {
    unsigned long ul = val;
    Console::WriteLine((UInt32)ul);
  } else {
    Console::WriteLine("conversion failure.");
  }
}


トマト  2009-09-05 01:56:02  No: 70867

テキストボックスに
"11112222"と記入しその記入された'文字'を取得してを自作関数readData(unsigned long deta)に渡す処理だったので

みぃ様のご指摘通り
>文字列を数値に変換
したかったので見よう見まねでキャストしてみました

Blue 様の
>this->textBox1->Textの値を数値で取りたいのであれば、UInt32::TryParseあたりで変換してください。
>ちゃんとエラー処理できますし。
これ!やりたかったんです。

http://imagingsolution.blog107.fc2.com/blog-entry-36.html
を真似てParseでつくってたんですが、
using namespace Systemのメンバではない?エラーが出て
何のクラスなのかなのか調べきれなくて断念して、
strtoul()を使えるように型変換を繰り返してました

>デバックエラー
とは?
実は、データベースにアクセスしているところで接続できていなかったようで
-----------------------------------
readData(unsigned long data); //DBアクセス
------------------------------------
の入り口にデータベース接続部を書いているのですが
その部分でデバックエラーだったようでした

conninfo = "host=localhost dbname=postgres user=postgres password=postgres";

    conn = PQconnectdb(conninfo);

--> if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, 
         "Connection to database failed: %s",PQerrorMessage(conn));
        exit_nicely(conn);
    }
ブレークポイントの使い方が分かっていなくてさっき教わり
どうやら
if (PQstatus(conn) != CONNECTION_OK)に入っていっているのを
確認しました。

コンソールでは、接続できていたんですが
まだリンクのし忘れてる部分でもあるのでしょうか?


επιστημη  URL  2009-09-05 02:04:14  No: 70868

実行できているならリンクエラーはありません。
# DLLの実行時loadでもやってない限り。

で、エラー・メッセージ:PQerrorMessage(conn) は何と言ってるんですか?


トマト  2009-09-05 02:16:21  No: 70869

重ね重ね申し訳ありません
本当にありがとうございます

>エラー・メッセージ:PQerrorMessage(conn) は何と言ってるんですか?
「子を評価できません」になっていて
connに入っているのは、0x004D1CB8みたいです。


επιστημη  URL  2009-09-05 06:18:11  No: 70870

PQerrorMessage(conn) に到達するまでステップ実行しましたか?


トマト  2009-09-07 19:20:00  No: 70871

>PQerrorMessage(conn) に到達するまでステップ実行しましたか?
ステップ実行とは(F10)を押したり、関数なら(F11)で関数の中の
ステップに入っていたりですよね?

PQstatusは以下のようにするとifの中に入ってしまいました
if (PQstatus(conn) == CONNECTION_BAD)
    {
         fprintf(stderr, "Connection to database failed: %s",
                PQerrorMessage(conn));
        exit_nicely(conn);
    }
流れ的には、
Form1で
textBox1に何か数字を記入してもらう
button1を押下したら取得した文字列を数字に変換して
データベースにアクセスしに行く
/* ******************************************************* */
int getData(unsigned long uid, char* status){
   int ret;
   ret =readData (code, "'OK'");
    
   if( ret == 1 ){
        printf("detabase error status\n");
        return 1;
    }
   printf("readData() completed successfully!\n");
   return 0;
}
/* ******************************************************* */
int readData(unsigned long code, char * status)
{
    const char *conninfo;
    PGconn     *conn;
    PGresult   *res;
    
    conninfo = "hostaddr=localhost dbname=firmo01 
                port=5432  user=postgres password=postgres";

    conn = PQconnectdb(conninfo);
    if (PQstatus(conn) != CONNECTION_OK)
    {
         fprintf(stderr, "Connection to database failed: %s",
                PQerrorMessage(conn));
        exit_nicely(conn);
    }
/* ******************************************************* */

//ボタン押下時の処理
private: System::Void button1_Click(System::Object^sender,System::EventArgs^  e) 
{
   char *endptr;
   unsigned long figure;

   String ^str;
   char buf[255];
   memset(buf, 0, 255);
   
   str = this->textBox1->Text;
   sprintf_s(buf, 100, "%s", str);

   figure = strtoul(buf, &endptr, 10);
   getData(figure,"'OK'");
}


επιστημη  URL  2009-09-07 20:32:21  No: 70872

だーかーらー...
エラー・メッセージ:PQerrorMessage(conn) は何と言ってるんですか?


トマト  2009-09-07 21:51:02  No: 70873

すみませんっ
PQerrorMessageの使い方が間違えてました

"ERROR : PQconnectdb() -unknown option 'hostaddr'"
と表示されてました


YuO  2009-09-07 21:58:39  No: 70874

メッセージそのままでは?
hostaddrなんてオプションは知らない,といっているのですから,そこが間違いなのでしょう。

実際,2009/09/07(月) 10:20:00投稿分のコードでは,conninfoにhostaddrという文字列が見受けられます。
おそらく,hostと書くべきなのだと思いますが……。


Blue  2009-09-07 22:27:59  No: 70875

>   str = this->textBox1->Text;
>   sprintf_s(buf, 100, "%s", str);
>
>   figure = strtoul(buf, &endptr, 10);
結局 UInt32::TryParse使ってないのか、、、
sprintf_sで%sがSystem::Stringに対応しているってMSDNに書いてあったけ?


επιστημη  URL  2009-09-07 22:31:33  No: 70876

> sprintf_sで%sがSystem::Stringに対応しているってMSDNに書いてあったけ?
可変長引数は引数の型チェックを素通りするから、
エラー出なくてうまくいってる"つもり"なだけかもー。


トマト  2009-09-07 22:41:34  No: 70877

>おそらく,hostと書くべきなのだと思いますが……。
hostとした場合は、
fe_sendauth : authentication type 5 not supported
になってしまいました

http://www.ezms.net/guide/util/cse_trouble_20060728_001.html
に乗っていた方法を試してみたら一応接続をするようになれました
CSEが"MD5"非対応だった?って事からかも・・・?


トマト  2009-09-07 22:44:35  No: 70878

一応接続したんですが
そのあと
すぐ、デバッグが途中で止まってしまうので強制解除?
なので
>UInt32::TryParse
にて書き直してみます。


トマト  2009-09-07 23:09:07  No: 70879

επιστημη様の
TryParseに変更してデバックしたら動くようになりました!

本当に皆様いろいろありがとうございました


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加