warning C4793: COleControl::`vcall'{540}”: ネイティブ関数としてコンパイルされました

食後に椅子でひと眠りしている間にヘルプのダウンロードが完了していた。日付が変わっているので新しいエントリを起こすことにする。

IMG_20190107_092449_thumb[2]

ノートパソコン(lenovo)の写真をスマホで取ってPCに落としたが、うまく同期が取れない。「ダウンロード」で何とか取り出せたが…まぁ、これはあとで見ることにしよう。ヘルプを「?」で開いてみた。

各プロジェクトのディレクトリの一覧 (プロジェクト単位) を指定することも、ユーザー、プロジェクト構成、および対象プラットフォームごとの組み合わせ (ユーザー単位) を指定することもできます。
ユーザー単位のプロパティ シートは、コンピューター上の特定のユーザーのすべてのプロジェクトに影響を与えます。

プロジェクト単位にパスを設定するようになっているが、ユーザ単位でも設定できるようになっているようだ。いや、現実にはそれはできないのではないだろうか?「VC++ ディレクトリ」タブには何も入力することができない。また、仮に「ユーザ単位」にパスを指定できるようになっていたとしても、それでは不都合だ。必要なのは「solution単位」でパスが指定できることなのだから…

プロジェクトのプロパティのVC++ディレクトリ→インクルードディレクトリで開かれるパネルは VS 2017 の場合とまったく同じだ。ここに以下の3行を追加してビルドできた。

$(SolutionDir)ZelkovaDLL
$(SolutionDir)ZelkovaDLL\INCLUDE
$(VCInstallDir)VC\atlmfc\include

DLLの場合、以下の4つのエラーが出ている。

1>SRC\COMDEBUG.CPP(28): error C2146: 構文エラー : ‘;’ が、識別子 ‘errno_t’ の前に必要です。

1>SRC\COMDEBUG.CPP(28): error C4430: 型指定子がありません – int と仮定しました。メモ: C++ は int を既定値としてサポートしていません

1>SRC\COMDEBUG.CPP(28): warning C4273: ‘fopen_s’ : dll リンクが一貫していません。

1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(236) : ‘fopen_s’ の前の定義を確認してください

最初のエラーは「__checkReturn_wat」が定義されていないためだ。この名前はcrtdefs.hで定義されている。このヘッダファイルは以下のフォルダに入っている。

c:\program files (x86)\microsoft visual studio 8\vc\include\crtdefs.h

これをインクルードパスに追加してみよう。以下を追加してみたが、効かない。

$(VCInstallDir)VC\include

VS 2010 ではこの位置にこのファイルが存在していない可能性がある。いや、存在している。考えられるのは$(VCInstallDir)が「Microsoft Visual Studio 10.0」を指していない可能性だ。というのは、このファイルをダブルクリックで開こうとすると、VS 2005 かないし、VS 2017 で開こうとする動作になるからだ。つまり、VS 2017 がすでにインストールされているために誤動作しているのではないか?ということが考えられる。マクロを使わずに直接上のパスを記入してみよう。

ダメだ!通らない。なぜだろう?VS 2010 のcrtdefs.h には「__checkReturn_wat」が入っていない。COMDEBUG.CPPで以下の行をコメントアウトしてコンパイルできた。

_CRTIMP __checkReturn_wat errno_t __cdecl fopen_s(__deref_out_opt FILE ** _File, __in_z const char * _Filename, __in_z const char * _Mode);

「_get_amblksiz」と「_set_amblksiz」も未定義になる。これらもコメントアウトできた。これでDLLはビルドできた。GCでは’ExportClasses.h’が見つからないというエラーになる。これは以下のパスにある。

d:\ZELKOVA_2018\ZELKOVA\ZelkovaDLL\INCLUDE\ExportClasses.h

これはプロジェクトのインクルードパスに以下を追加して解決した。

$(SolutionDir)ZelkovaDLL\INCLUDE

OCXの場合も同じだ。OCXでは警告が2つ出ている。

warning MSB8012: TargetPath(D:\ZELKOVA_2019\ZELKOVA\Debug\ZelkovaZ3.dll) が Linker の OutputFile プロパティ値 (D:\ZELKOVA_2019\ZELKOVA\Debug\ZelkovaZ3.ocx) と一致しません。このため、プロジェクトが正常にビルドされない可能性があります。この問題を解決するには、$(OutDir)、$(TargetName)、および $(TargetExt) の各プロパティ値が、%(Link.OutputFile) で指定されている値と一致することを確認してください。

warning MSB8012: TargetExt(.dll) が Linker の OutputFile プロパティ値 (.ocx) と一致しません。このため、プロジェクトが正常にビルドされない可能性があります。この問題を解決するには、$(OutDir)、$(TargetName)、および $(TargetExt) の各プロパティ値が、%(Link.OutputFile) で指定されている値と一致することを確認してください。

実際には同じ内容なので警告は1つと見てよい。要は、「TargetPath と Linker の OutputFile」の値が異なるということのようだ。この違いは「DLL」と「OCX」の違いだ。リンカーの出力ファイルがDLLになっている。これをOCXに変えればよいのだろうか?この部分がDebugモードとReleaseモードでは異なるものになっている。Releaseモードでは

$(OutDir)$(TargetName)$(TargetExt)

のように書かれている。Debugモードでは

$(SolutionDir)\$(Configuration)\$(ProjectName).dll

だ。最後のdllを$(TargetExt)のように書き換えてみよう。いや、見るところを間違えた。この違いはOCXではなく、GCのプロパティだ。OCXでは出力ファイルはOCXになっている。構成プロパティ→全般→ターゲットの拡張子が「.dll」になっているので「.ocx」に変えてみよう。通った。レジストリ登録に失敗している。

regsvr32 /s “D:\ZELKOVA_2019\ZELKOVA\\Debug\ZelkovaZ3.ocx”

このコマンドをPowerShellで実行してみたところ、下記のエラーになった。

エラーコード:0x80040201

このエラーは管理者権限がない場合に発生するとある。今度は成功した。これは結局Visual Studio を起動する際に管理者権限で実行していないためだろう。⇒起動し直してDLLのエラーは出ないようになったが、VBでエラーが発生する。

vbc : error BC40057: プロジェクト レベルのインポート ‘ZelkovaBeta’ で指定された名前空間または型が、パブリック メンバーを含んでいないか、または見つかりません。名前空間または型が定義されていて、少なくとも 1 つのパブリック メンバーを含んでいることを確認してください。また、インポートされた要素名がエイリアスを使用していないことを確認してください。

VBの参照にdebug\ZelkovaZ3.ocxを追加しようとしたら、以下のようなパネルが出た。

image_thumb[2]

「はい」で閉じたのはよいが、「対象の.NET Framework」を変更しなくてはならない。VBの.NETは現行では2.0になっている。OCXで必要な.NETのバージョンが分からないので取り合えずこのまま進むことにする。「ツールボックスにアイテムの選択」を実行しようとして、以下のエラーになった。

image_thumb[5]

ツールボックスにOCXを追加してエラーが発生した。プロジェクトファイルが壊れたというので「修復」を選択した。追加したOCXはツールボックスから消えている。もう一度実行してみたが、同じ現象が起きる。つまり、OCXをVBフォームに貼り込むことができない。

かなりまずいことになってきた。OCXをフォームに貼り込むと、IDEではこのオブジェクトを描画するためにOCXを起動する。この際何かエラーが発生して異常終了しているものと思われる。ツールボックスから挿入で参照解決するというのは「奥の手」なのでそれができないとほとんどお手上げになってしまう。

Releaseモードで試してみることにする。どうもReleaseモードとDebugモードで個別にインクルードパスを切る必要があるようだ。かなり馬鹿げているという気がするのだが…馬鹿げているというよりは「ひどい話」だと思う。IDEが落ちているので、「管理者権限で実行」が外れているのではないか?以下のようなエラーが出ている。

2>D:\ZELKOVA_2019\ZELKOVA\ZelkovaZ\ZelkovaCtrl.cpp : warning C4793: COleControl::`vcall'{540}”:  ネイティブ関数としてコンパイルされました:
非 clrcall 仮想呼び出しサンクは、ネイティブとしてコンパイルする必要があります

この警告はデバッグモードでも出ているが、ビルドは完了している。リリースモードでは警告をエラーとみなす設定になっているため、ビルドは失敗に終わる。このエラーはCOleControlの仮想関数に関わるものなのでアプリからは調整できないので、プロジェクトのプロパティで「警告をエラーとして扱う」を「いいえ」に変えることにする。

VBのプロパティでコンパイルタブ→詳細コンパイルオプション→対象のフレームワークの値を.NET Framework 4に切り替えて名前空間の問題は解決したが、まだエラーが残っている。

D:\ZELKOVA_2019\ZELKOVA\ZekovaVB\CardBox.Designer.vb(97) : error BC40000: ‘Microsoft.VisualBasic.Compatibility.VB6.CheckBoxArray’ は旧形式です: ‘Microsoft.VisualBasic.Compatibility.* classes are obsolete and supported within 32 bit processes only. http://go.microsoft.com/fwlink/?linkid=160862′

のようなエラーが、以下の要素で発生している。項目11以下は関数。

  1. CheckBoxArray
  2. ButtonArray
  3. ComboBoxArray
  4. PanelArray
  5. TextBoxArray
  6. ButtonArray
  7. FixedLengthString
  8. SetDefault
  9. GetItemString
  10. GetHInstance
  11. FontChangeName など
  12. TwipsToPixelsX
  13. PixelsToTwipsX
  14. CopyArray

これらはすべてVB6の残留物と見られる。このエラーは多分警告に落とすことができ、VBでは警告を無視するようになっているので、多分実行は可能になると思われるが、.NETの将来バージョンないし、64ビット版では完全に廃止されることになっている。いや、違う。現行では「すべての警告をエラーとして扱う」ようになっている。

このエラー ObsoleteAttribute を警告に落とす方法が見つからない。暫定的に「すべての警告を表示しない」でビルドしてみる。やはり、OCX が認識されていないという問題が残る。今度はツールボックスからフォームにOCXを挿入できた。これで一応ビルドは通ったが、実行しようとしたらIDEが落ちてしまった。

Zelkova_2018とZelkova_2019が同じモジュールを使っているためと考えられる。Zelkova_2018を閉じてから再試行してみよう。「管理者権限で起動」を忘れていた。今度は走った。ようやく、懐かしいエラーパネルに再会できた。LoadNameProperty のエラーだ。

image_thumb[8]

このエラーが最初に検出された日付を調べてみよう。2018/12/27だ。このエラーは

チャンネルギャップの値がゼロになっている.この値は1~100の間でなくてはならない.⇒新規ファイルでは既定のテーマが使われるが,common files\ゼルコバの木系図\templates に標準画面設定.TMZ ファイルが存在しないためだ.これはまだアプリをインストールしていないためだ…

という理由で起きている。ようやくデバッグに戻ってきた。さて、ここからどうするか?だが、ここでデバッグに入るより、先に2017への移行を急いだ方がよいのではないだろうか?多分2017への移行は2010への移行とほぼ同等手順で実現できるのではないかと思う。あれこれやるより手順を飲み込んでいる時点で片付けてしまった方がよい。ソリューションやプロジェクトは修正内容が生かせると思うので、2010→2017というステップでやってみることにする。

Visual Studio 2017で2010でビルドしたソリューションを開くと、下記のパネルが出る。

image_thumb[11]

これで「プラットフォームツールセット」は v100からv141に上がった。それ以外には何も表示されない。

食事してきた。通知を見ると「誤変換報告」が「無数」と言ってよいくらい入っている。切りがないので「すべての通知をクリア」することにしたが、一番最後に気になる通知が入っている。いま開けたら消えていたが、「ヘルプエージェントを開始しました」とか何とかいうメッセージだった。「誰もそんなこと頼んでない」っつーの。ビルドすると大量のエラーが発生するが、前に出ていた「インクルードパス」の問題はきれいに解消している。以下のような警告が発生している。

1>d:\zelkova_2020\zelkova\zelkovadll\include\nodule.h(800): warning C4458: ‘cid’ を宣言すると、クラス メンバーが隠蔽されます。

cid という変数はクラスメンバーとして宣言されているが、スコープが違うのだから問題ないはずだ。いつからそういう話になったのか知らないが、C++の規約にはそのようなことは書いてないはずだ。警告だから無視してもよいのだが、ともかく直しておこう。

少しややこしい話が出てきた。

1>d:\zelkova_2020\zelkova\zelkovadll\src\bpagesetupdialog.cpp(288): warning C4840: 可変個引数関数の引数としての、クラス ‘ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<_CharType>>>’ の移植性のない使用法
1>        with
1>        [
1>            _CharType=char
1>        ]

オンラインヘルプによれば、static_cast<int>(s) のように書き直すべきだという。これはどうもちょっと堪ったもんではない。ひどい言いがかりと言ってよいくらいだ。bprintfがエラーになるとしたら何百いやそれ以上の修正が必要になる。いや、そういう問題ではないかもしれない。エラーが出ている個所はchar*ではなく、CStringを引数で渡している個所だ。AllocSysStringを使って明示的にBSTRに変換する必要がある。

「クラス メンバーが隠蔽されます」の修正箇所は山のようにある。ソースファイルがDLLだけで79本ある。仮にファイルが100本で1本当たり10箇所修正するとすれば、修正は1000件におよぶ。1箇所でも間違えればアウトだ。必ずバグになって返ってくるだろう。本当はこのようなエラーが出ている個所を吟味して最適修正すべきなのだろうが、ともかく今は機械的に書き換えてゆくしかない。

最近では #ifdef などの条件コンパイル文に「日本語」を使うようにしているが、ここに来て急にその構文がうるさくなってきた。VBでも同じことをやっているがこちらは元々多少の制限はあったが、C++にはまったく規制が掛かっていなかったのに VS 2017 になって、少なくとも以下のような構文は禁止されるようになった。①文中に「→」あるいは「->」を用いてはならない。②文頭に使ってはいけない文字がある。今のところは『「、◆』だけだが、もっといろいろありそうだ。

つまり、日本語文字の中で「特殊記号」に当たるものは使えない場所がある。数式記号は元々使えないので半角の「-」や「>」は使えない。ただし、全角の「-」は問題ないようだ。今のところまだプログラムをすべて日本語で書くというところまでは進んでいないが、VBではすでに多少それを試みている。プログラムをすべて日本語で書くことができれば(実際多分それは現状でもほとんど問題なく可能だと思われる)プログラミングは相当楽になるような気がする。#ifdef 文の中に日本語を使っているのは、それがコメント(修正履歴)の代用になるためだ。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA