61101


現在、RAD Studio 10.3でプログラミングを行っています。

[code]

    char Buf[256];
    ---------------(中略)---------------------
    GetPrivateProfileString("LANG_JPN","TOOLBAR_SERVER_STOP","Stop",Buf,40,".\\Japan.ini");
    
[/code]

exeファイルと同じフォルダにあるJapan.iniファイルから文字データを取り出そうとしているようなのですが、次のようなエラーが発生します。

[code]

    [bcc32c エラー] Main.cpp(1383): no matching function for call to 'GetPrivateProfileStringW'
      winbase.h(4417): candidate function not viable: no known conversion from 'const char [9]' to 'LPCWSTR' (aka 'const wchar_t *') for 1st argument
    
[/code]

このエラーの回避方法を教えて下さい。


CC BY-SA 4.0
2019-12-04T08:00:45.097
61092
2022-11-07T12:41:58.880
2022-11-07T12:41:58.880
4236
35993
question
c++ windows winapi
GetPrivateProfileString関数でエラー


Win32 API の使用経験はありますか？  
`GetPrivateProfileString` という API 関数は、実は存在しません。  
`GetPrivateProfileString` は、実際には下記のどっちか片方の別名となっています。  
`GetPrivateProfileStringA` という `ANSI` 版 (`char` 系を引数に受け取る)  
`GetPrivateProfileStringW` という `WideChar` 版 (`wchar_t` 系を引数に受け取る)

Visual Studio 等では、プロジェクトのオプションでどっちを使うかを切り分けています。オイラが使ったことのない RAD Studio
でも同等のはず。んで、今のエラーメッセージからすると、あなたのプロジェクトは `UNICODE` 設定 (`WideChar` 側を使う)
になっているようです。

なぜこんな複雑怪奇な仕様になっているかというと Win95 系と WinNT 系で Win32 API
の実装が異なっていたという事情があるのですが、もう既に Win95 系が絶滅している関係で新しく作るソフトで `ANSI`
版を使う理由は何一つなく、ゆえにプロジェクトのデフォルト値は `UNICODE` 設定となっています。（`A`
系は多国語対応できないしエンコード変換が入るので遅い）

RAD Studio でどうかは知りませんので以下は Visual Studio の場合ですが

  1. `_TCHAR` を使い `ANSI` / `WideChar` 両方に対応したコードにする

`char` 型ではなく `_TCHAR` 型を使い、かつ文字列リテラルは `_T("...")` とする  
`#include <tchar.h>` が必要

[code]

    _TCHAR buf[40];
    GetPrivateProfileString(_T("LANG_JPN"), _T("TOOLBAR_SERVER_STOP"), ... );
    
[/code]

`ANSI` ビルドすると Win95 用 EXE が作れ（日本語オンリー) `UNICODE` ビルドすると WinNT 用 EXE
が作れ多国語対応になります。

  2. `WideChar` 限定とする

`char` 型ではなく `wchar_t` 型を使い、かつ文字列リテラルは `L"..."` とする  
明示的に `W` 版 Win32 API を呼ぶ  
こちらの場合 `#include <tchar.h>` は不要

[code]

    wchar_t buf[40];
    GetPrivateProfileStringW(L"LANG_JPN", L"TOOLBAR_SERVER_STOP", ... );
    
[/code]

これだと多国語対応が自動でできてしまいます。が Win95 には非対応となります。

  3. プロジェクトの設定を `ANSI` に変えちゃう

今のソースコードを変えなくていいはず。その代わり多国語対応はできません（日本語 Windows を使うと中国語やタイ語を使うことはできなくなる）

  4. `ANSI` API を明示的に使う

プロジェクトの設定は `UNICODE` のままで明示的に `ANSI` 版 API 関数を使ってもいいです。デメリットは 3. に同じ。

[code]

    char buf[40];
    GetPrivateProfileStringA("LANG_JPN", "TOOLBAR_SERVER_STOP", ... );
    
[/code]

移植前ソースコードが `FILE* f=fopen(filename, "rb");` のようにバリバリに `char` 型を使っているなら 3. か 4.
のほうが書き換え量は少ないですが、いまどき流ではないっすね。日本語限定がとても痛いっす。かといっていきなり `WideChar`
版に全部直すのも困難かもしれないし、どっちにするかはお任せします。


CC BY-SA 4.0
2019-12-04T10:35:26.937
61101
2019-12-05T01:23:22.773
2019-12-05T01:23:22.773
8589
8589
61092
answer


質問者さんの一連の質問を読む限り、ご自身で書かれたコードではなく他人の書かれたコードを移植していると理解しました。  
他人の書いたコードをANSI / Unicode変換するのは危険です。タグ指定されているC++言語とはあまり関係なく、RAD
Studio側だと思いますが、元通りANSIでビルドされることをおすすめします。

  * [inet_addr()という関数でエラーがでる](https://ja.stackoverflow.com/q/60953/4236)
  * [GetPrivateProfileString関数でエラー](https://ja.stackoverflow.com/q/61092/4236)

などは、ANSI / Unicodeを切り替えたことによって発生しているコンパイルエラーですが、このようにエラーが発生してくれる場合はまだいいのですが、

[code]

    void* memcpy( void *dest, const void *src, size_t count );
    
[/code]

`memecpy`などのように`void*`が使われてしまうと、本来ANSI文字列が必要とされている箇所がUnicodeに切り替わっていてもコンパイラーは検出できず、実行時に不可解な現象が発生します。こういったコード上で見えない問題を回避するためにもANSIでビルドすべきです。

最近あった例で[「Windows
10」のシャットダウンを妨げる謎の「G」アプリ、マイクロソフトが説明](https://japan.zdnet.com/article/35145860/)では

[code]

    L"GDI+ Hook Window"
    
[/code]

というUnicode文字列をANSI APIに渡してしまったがために`"G"`と解釈されてしまう現象を引き起こしています。


CC BY-SA 4.0
2019-12-05T00:00:04.360
61114
2019-12-05T00:44:41.807
2019-12-05T00:44:41.807
4236
4236
61092
answer