HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2023
0503
youdai64bit版のSQLite(sqlite3.dll)を、HSP3 64bit版で使用したいです6解決


youdai

リンク

2023/5/3(Wed) 18:06:31|NO.99377

64bit版のSQLite(sqlite3.dll)を、HSP3 64bit版で使用したいです。

32bit版のSQLiteは、HSP3 32bit版のSQLeleモジュールで使用できるのですが、HSP3 64bitではSQLeleは使用できません。

HSP3フルセット版の中に収録されているSQLele.hspを改造すればできるのではないかと、試行錯誤してみたのですが自分のレベルではできませんでした。
HSP3 64bit版の特徴で文字コードがUTF-8なのですが、その関係で64bit版で動作しないのかなという感じを受けました。
他にもSQLeleはkernel32.dllを呼び出してる部分があって、その部分が64bitアプリケーションのせいで呼び出せないのかなという感じも受けました。

使用したSQLiteは以下の64bit版を使用しました。

SQLite Download Page
https://sqlite.org/download.html

ソースコード
sqlite-amalgamation-3410200.zip

バイナリファイル(sqlite3.dll と sqlite3.def)
sqlite-dll-win64-x64-3410200.zip

どうしたら、SQLele.hspを64bit版対応にできるでしょうか?
SQLite 64bit版をHSP3 64bit版で使えるのであれば、SQLele方式の文法のモジュールでなくても構いません。

ぜひご教授お願い致します。



この記事に返信する


usagi

リンク

2023/5/19(Fri) 21:48:31|NO.99465

hsp3 64bit版は64ビットアプリとしては動きますが、
言語として64bit整数、ポインタが使えません。

ですから、現状では #func や varptr を使うSQLiteの移植は
かなり難しいと考えた方が良いかとは思われます。
hsp3 64bit版はまだβ版ですから待つしかないかもしれませんね。。。

※余談※
ちなみにご存じでしたら申し訳ないですが、
WOW64側の"kernel32.dll"は64bitでございますから
hsp3 64bitで呼び出せます。(32bitのエミュレート)

#include "hsp3_64.as" #uselib "kernel32" #func global Beep "Beep" sptr,sptr Beep 750, 300 ; ビープならすだけ

ですから、大きな壁として sqlite3_open へファイルパスのポインタを
渡すところがまずは難しいかもしれませんね。



usagi

リンク

2023/5/19(Fri) 22:03:52|NO.99466

↑ あっ、嘘行ったかもしれないですSystem32側の間違え。。。
お伝えしたかったのはKernel32より64ビットポインタ関係で難しいかもというとこです。すみません。



youdai

リンク

2023/5/21(Sun) 16:45:01|NO.99481

アドバイスありがとうございます。

HSP3 64bit版でint64を扱う方法ですが、以下のモジュールを使えば可能かもしれません。

HSPInt64.dll - HSP3(64bitランタイム)で64bit整数演算を行うためのプラグイン
https://hsp.moe/#hspint64

説明は以下のように書いてありました。

・HSP3(64bitランタイム)でlonglong型(64bit)の変数を扱うことができます。
・int(); lpeek(); lpoke; varptr(); dupptr(); callfunc(); の64bit版が使用できます。
・コールバック関数(64bit版)の作成に対応しています。
・UTF-16型文字列変数やfloat型変数をサポートしています。

もしint64がネックになっているのだとしたら、これを使用すればSQLeleをHSP3 64bit版でSQLeleを使えるようになるのでしょうか?
使うとしたら、どの部分に使えばいいのでしょうか?



TOMATO

リンク

2023/5/21(Sun) 22:27:32|NO.99483

ぱっと見た感じ以下の課題がありそうでした。
64bitとUTF-8が余計にややこしくしている感じがあります。

・SQLite.dll側のデフォルトの文字コードはUTF-8である
・したがって、SQLele.hsp の Shift_JIS⇔UTF-8変換コードは不要
(MultiByteToWideCharとWideCharToMultiByteはいらない)

・HSPの64bitランタイムはUTF-8ですが、#funcなどのDLL呼び出しパラメータであるstr,sptrは互換性のためにShift_JISに変換されます。
wstr,wptrも同様にUTF-8からUTF-16に変換されます。
これは、Windows APIが日本語環境のデフォルトのANSI版がShift_JIS、WIDE版がUTF-16になっているためです。
ですので、文字化けしないように意図した文字コードで渡るように記述する必要があります。
方法としていくつかありますが、
1つ目はstrやsptrをvarに変更する。2つ目はHSPInt64.dll を使う、3つ目はSQLiteのUTF-16版の関数を使用するといった感じでしょうか。

1つ目の場合なんですが…、今回の場合使えそうな場所がぱっと見なさそうでした。
SQLiteのハンドルをvarで渡すのが、難しそうといった感じです。

2つ目の場合は、

sqlite3_prepare_v2 pdb, atmp, strlen(atmp), pstm, 0


ret = cfunc64i( sqlite3_prepare_v2, pdb, varptr(atmp), strlen(atmp), pstm, 0)
のような感じに書き換える必要があります。
(※ 動かしていないので、間違ってるかもしれない)

3つ目の場合は、以下を参考にUTF-16版の関数を使うように変換します。
https://www.sqlite.org/c3ref/open.html

以下のような感じに書き換えます。

#uselib "sqlite3" #func sqlite3_open "sqlite3_open" sptr, var


#uselib "sqlite3_64" #func sqlite3_open16 "sqlite3_open16" wstr, var

・SQLite3.dll は SQLite3_64.dll みたいにリネームするのが無難
(64bitランタイムで間違って32bit版DLLを呼び出すと、非常に分かりにくいエラーメッセージが出るため)
・SQLele内はポインタを32bitのintで取り扱っている箇所がちょいちょいあります。
HSPInt64のInt64型を使わないといけないケースがありそうです。



usagi

リンク

2023/5/22(Mon) 05:38:09|NO.99484

へぇー、そんな便利なモジュールがあるのですね。
youdaiさんが仰られるように、hsp標準機能64bitの置き換えがあるので、
あとは使いたい機能を呼び出すだけですね。

全ての機能を置き換えるのは時間が掛かるので、DBとしてシンプルな部分のみ呼び出してみました。
こちらでは動作確認できてますので、置き換えのご参考になれば幸いです。



#include "hsp3_64.as" #include "hspint64.as" ; ここを参考に使いたいものを関数や定数を準備 ; https://sqlite.org/capi3ref.html #uselib "sqlite3_64" ; 64dllをリネームしてスクリプトと同じ所へ配置する事。 #define BUF_SIZE 512 #define NULL 0 #define SQLITE_OK 0 #func sqlite3_open "sqlite3_open" wptr, wptr #func sqlite3_close "sqlite3_close" wptr #func sqlite3_exec "sqlite3_exec" wptr, wptr, wptr, wptr, wptr #func sqlite3_free "sqlite3_free" wptr ; DBオープン filename = "sample.db" pDB = int64(0) res = cfunc64i( sqlite3_open, varptr64(filename), varptr64(pDB)) if res != SQLITE_OK : dialog "DBオープン失敗" : end onexit goto *SQL_END ; テーブル作成 res = cfunc64i( sqlite3_exec, pDB, "CREATE TABLE IF NOT EXISTS MemoTable (ID INTEGER PRIMARY KEY, Memo)", NULL, NULL, varptr64(pErrMsg)) if res != SQLITE_OK : gosub *SQL_ERR_MES ; UI msg = "オナカスイタ" input msg, 380, 25 button goto "書き込み", *L_INS stop *L_INS color:boxf:color 255,255,255:pos 0,48 ; ここからクエリ実行 ;---------------------------- pErrMsg = int64(0) ; インサート res = cfunc64i( sqlite3_exec, pDB, strf("INSERT INTO MemoTable (Memo) VALUES ('%s')", msg), NULL, NULL, varptr64(pErrMsg)) if res != SQLITE_OK : gosub *SQL_ERR_MES ; セレクト cbQuery = callback64_new( 4, *SQL_CB) pCbQuery = callback64_getptr(cbQuery) res = cfunc64i( sqlite3_exec, pDB, "SELECT ID, Memo FROM MemoTable ORDER BY ID DESC", pCbQuery, NULL, varptr64(pErrMsg)) if res != SQLITE_OK : gosub *SQL_ERR_MES ;---------------------------- stop ; コールバック *SQL_CB ; int (*callback)(void*,int, char**, char**) mes "-----------" num = callback64_getprm(cbQuery, 1, RET_INT) ppText = callback64_getprm(cbQuery, 2, RET_INT64) dupptr64 pText, ppText, 8*num, 2 ppName = callback64_getprm(cbQuery, 3, RET_INT64) dupptr64 pName, ppName, 8*num, 2 repeat num dupptr64 txt, qpeek(pText, cnt*8), BUF_SIZE, 2 dupptr64 name, qpeek(pName, cnt*8), BUF_SIZE, 2 mes strf("%s: %s\t", name, txt) ; 今回は直接表示 loop return ; エラーメッセージ *SQL_ERR_MES dupptr64 errMsg, pErrMsg, BUF_SIZE, 2 mes errMsg cfunc64v sqlite3_free, pErrMsg pErrMsg = int64(0) return ; DBクローズ *SQL_END res = cfunc64i( sqlite3_close, pDB) end

補足で、ファイル書き込み禁止にしたり、トークンに'など解析エラーがあった場合エラーメッセージ出るようにしてます。
また、直接クエリをインプットに打ち込めるようにして、リターンでクエリ結果を文字列で返すようにしても、
シンプルかつ色々使える形に出来そうですね。



youdai

リンク

2023/5/23(Tue) 11:05:57|NO.99490

usagiさん、TOMATOさん、アドバイスありがとうございました。
教えていただいたアドバイスを参考にして、64bit版のSQLiteを実装することができました。
今回の質問は自分の知識だけではとても実装することができなかったと思うので、とても助かりました。
SQLが使えるようになるとプログラミングの幅がすごい広がるので、自分にとって非常に大きな前進になりました。



ONION software Copyright 1997-2023(c) All rights reserved.