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


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
1022
ぶどう色llmod3とkernel32.asの共存6解決


ぶどう色

リンク

2018/10/22(Mon) 15:41:35|NO.85655

こんにちは。久々にお世話になります。
llmod3とkernel32.asの共存についての質問です。

現在作成しているコードでは、訳あってllmod3と別のモジュールで呼び出すkernel32.asが共存しています。
llmod3.hsp内ではkernel32.dllの関数が定義されているため、kernel32.asとはその部分で競合します。
ですから、llmod3.hspをインクルードして、競合する関数を#undef命令で消し、それからkernel32.asをインクルードしています。

しかし、その様にコードを記述すると、llmod3.hsp内で使用しているkernel32.dllの関数が文法エラー(2)となり、コンパイルできません。
一応、関数の定義はllmod3.hsp内のモノをkernel32.asのモノで上書きされても支障ない文法です。
また、kernel32.asをインクルードせずに、#undef命令のみの場合は文法エラーになりません。(つまり、#undef命令が原因ではない。)
故に、文法エラーとなる意味が分からないのですが、どなたかご存知ないでしょうか。

合わせまして、できればインクルードするファイルを書き換えずに、この症状を回避する方法もご教授頂けたらと思います。
(解決方法が無ければ、このコード用に別途llmod3のファイルを用意します)

皆様、宜しくお願いします。


#include "llmod3/llmod3.hsp" #undef FreeLibrary #undef GetProcAddress #undef lstrlen #undef LoadLibrary #include "kernel32.as"



この記事に返信する


掘木

リンク

2018/10/22(Mon) 23:25:45|NO.85657

これは現行のコンパイラの仕様上不可能です。あきらめましょう。

#undefの使い方に問題があります。
・#undefは「定義済みマクロ」の置き換え名称を解放するプリプロセス時解決命令です。
 #funcは定義済みマクロを生成するプリプロセス命令ではないので有効ではありません。

#undefは定義可能な名称の解放に対して、エラーを発行しません。
未定義の名称、本来解放できないモノに対して使用してもエラーになりません。

文法エラー扱いされる件に関しては、#undefの珍妙な動作とコードの最適化が関わってきます。
以下は、OpenHSPの動作を独自に解釈したものです。

イ.#deffunc、#moduleなどでプリプロセスがユーザー定義の名称に   新たな役割を与える場合に、名前持ちのラベルを用意する。 ロ.展開マクロ系のプリプロセス命令はコンパイラに定義を伝播しない。   #func、#deffunc等はプリプロセス命令に特定のフォーマット変換を掛けコンパイラに再送する。 ハ.#undefは名前持ちのラベルを検索対象から外す役割を担う。   コンパイラへの再送は行わない。 ニ.プリプロセス・コンパイラは生成されたラベルに対して、   被参照回数をカウントする機能を有する。 ホ.コンパイラはプリプロセスからラベル情報を受け取り、被参照回数を引き継げる。 ヘ.コンパイラは被参照回数が0回のラベルの定義プリプロセス命令に対して、   展開しない選択肢を持つ(不要コードの削除)

掲題のコードをhspcmpの実装レベルで追いかけます。

1.llmod3/llmod3.hspの内部でGetProcAddressを呼び出す命令を持ち、
  実行領域(module外)にその命令呼び出しがあるため、
  GetProcAddress(llmod3内)は被参照回数1以上になる。
2.掲題コードに戻り、#undefによりGetProcAddress(llmod3内)は検索対象から外れます。
  なおこのとき、「コンパイラへの引き継ぎ」もされません。
3.kernel32.asの内部で#func定義があり、その後呼び出しがないため、
  GetProcAddress(kernel32)は被参照回数0としてコンパイラに引き継がれます。
4.コンパイラはllmod3内のGetProcAddressの#func定義を見つけた際、
  名称検索によりGetProcAddress(kernel32)を発見し、被参照回数0により、
  cmpopt-optcode未規定(最適化する)に従い、この定義をスキップします。
5.llmod3内のdll_getfunc内で呼ぶGetProcAddressが未定義命令としてエラーになります。←文法エラー

cmpopt-optcodeの最適化を切る/kernel32.asのインクルード以降にGetProcAddressを呼ぶと、
4.#func命令により、GetProcAddress(llmod3)が解決コード上に乗る。
5.llmod3内のGetProcAddressが正常にコンパイルされる。
6.#undefがあった行は"undef"はコンパイラに再送されないため、GetProcAddressの名称が有効のまま進む。
7.kernel32.as内のGetProcAddressを定義する#funcによって名称二重定義となりコンパイルエラーとなります。←二重定義エラー

すでに試されてると思いますが、インクルード順を変えてもダメです。


これが本来意図した言語仕様なのか私は明確な答えを持っていない為、
バグとも仕様とも答えられません。



あらや

リンク

2018/10/23(Tue) 00:15:02|NO.85658

そもそもですが、さすがにkernel32.asの全ての関数を使っている訳ではないと思うので
インクルードするだけなのが簡単で便利なのはわかりますが
asファイルをインクルードせずに、必要な関数だけ自分で定義すればいいのでは?

もちろんllmod3.hsp内で定義されている関数を使う場合は
その使い方に合わせる形になりますが、
そこはまず変わらないと思うので気にしなくてもいいですし
そうすればllmod3.hspファイルを書き換える必要はないでしょう。



ぶどう色

リンク

2018/10/23(Tue) 01:19:14|NO.85660

>>掘木さん
HSPの内部処理レベルにまで言及して詳しく解説頂き、ありがとうございます。
とても分かりやすく、また納得できました。
#undefは#deffuncなどに対しても使えるので、憶測で#funcにも使えるだろうと考えておりましたが、ユーザーマニュアルにも「マクロ名の取り消し」としっかり書いてありましたね。
意図した動作かは分かりませんが、そういう動作をする以上は仕様と見なして、こちらがそれに合わせて開発を進める他ないですね。

>>あらやさん
言うまでもなく、おっしゃる通りです。
ただ、Win32APIをいくつも呼び出す場合、既に定義されているファイルがあるのに、一々あの中から探してきてコピペするのは生産性に欠ける気がします。
また、他の言語でも基本的には使用する関数だけを1つ1つ定義するのではなく、ヘッダーファイルを丸ごとインクルードすることが一般的ですから、1つ1つ定義するほがむしろ特殊な使い方に感じます。

しかし、HSPは相当特殊な言語なので、他の言語での常識が通用しないのは重々承知しております。。。



とあるプログラマ

リンク

2018/10/23(Tue) 05:28:35|NO.85661

終わったスレに返信するのもなんですが、llmod3.hspをコピーしてllmod3_2.hspなどの適当な名前つけて開き、#uselib "kernel32.dll"〜の部分を消して#include "llmod3\\llmod3_2.hsp"の前に#include "kernel32.as"を入れればいけます



ぶどう色

リンク

2018/10/23(Tue) 06:04:51|NO.85662

>>とあるプログラマさん
朝早くからご苦労様です。
一つ豆知識なのですが、通常インクルードするファイルはcommonフォルダ下のものを参照しますが、ソースコードと同じディレクトリ内に同名のファイルがある場合は、そちらを参照してコンパイルするようになっています。



とあるプログラマ

リンク

2018/10/23(Tue) 06:10:46|NO.85664

>>ぶどう色さん
豆知識ありがとうございます。ですが私はそれを承知済みの上 オリジナルのllmod3.hspと区別するためと、別のプログラムを書くときにもいちいちソースディレクトリにコピーする必要が無いためこちらの方法を書かせていただきました。



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