古いソフトの再ビルド

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
初心者

古いソフトの再ビルド

#1

投稿記事 by 初心者 » 18年前

古いプログラムのソースを知り合いからいただいたのでVisual Studio2005でビルドし直しているところですが、以下のようなエラーがでてしまって困っています。
解決策を教えていただけないでしょうか?
エラー内容
c:\C練習\テスト.cpp(1425) : error C2664: 'MultiByteToWideChar' : 5 番目の引数を 'u16 [/url]' から 'LPWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。

ヘルプファイルを読んでみたのですが、さっぱり分かりませんでした。
よろしくお願いします。

keichan

Re:古いソフトの再ビルド

#2

投稿記事 by keichan » 18年前

プロジェクト -> ***のプロパティ -> 構成プロパティ -> 全般
の中にある文字セットを [Unicode文字セットを使用する] から [マルチバイト文字セットを使用する]に変更してみてください。

初心者

Re:古いソフトの再ビルド

#3

投稿記事 by 初心者 » 18年前

> プロジェクト -> ***のプロパティ -> 構成プロパティ -> 全般
> の中にある文字セットを [Unicode文字セットを使用する] から [マルチバイト文字セットを使用する]に変更してみてください。

表記の通りやってみたのですが、結果は変わりませんでした。
デフォルトがマルチバイト文字セットになってました。
ソースの一部でものせた方がわかりやすいでしょうか?

GPGA

Re:古いソフトの再ビルド

#4

投稿記事 by GPGA » 18年前

プログラムが短いのであれば、全て乗せてもらったほうがいいですが
もし、かなり大きいというのであれば、MultiByteToWideCharを使用している行と
MultiByteToWideCharの5番目の引数に渡している変数の宣言部分および、u16をtypedefしている部分を
見せてください。

管理人

Re:古いソフトの再ビルド

#5

投稿記事 by 管理人 » 18年前

皆さんすみません、、
卒論で忙しくて家に帰れない&夜も眠れない毎日が続いています…;。
ひと段落したらまた顔を出しにくるようになりますので、ご迷惑をおかけしますがよろしくお願いします(_ _||)

初心者

Re:古いソフトの再ビルド

#6

投稿記事 by 初心者 » 18年前

> MultiByteToWideCharの5番目の引数に渡している変数の宣言部分および、u16をtypedefしている部分を見せてください。

よく分かりませんが関係ありそうな所をピックアップします。
これがエラーが出ている行です。
len = MultiByteToWideChar (CP_ACP, 0, msg, len, packet->text, len *2);
5番目の packet->text はそのまま変数の型宣言をしているところが見あたりませんでした。
いろいろ探してみたところ、
#include "packet.h"とincludeしているファイルの中に、
struct packetae
{
u8 no;
u16 len;
u32 object_id;
u16 model_id;
u8 type;
u16 color_id;
u16 font_id;
u32 language;
u8 name[30];
u16 text[0];
};

という記載がありました。
こんな感じで良いでしょうか?

GPGA

Re:古いソフトの再ビルド

#7

投稿記事 by GPGA » 18年前

textが他にどのように使われているか、気になるところですが

u16 text[0];

の部分を

wchar_t text[0];

に書き換えて、ビルドしてみてください。
これで問題なく、ビルドが通れば一番いいです。

もし、textが特殊な使われ方(ないとはおもうけど)をしていて、他でエラーが発生するようであるならば

MultiByteToWideChar(CP_ACP, 0, msg, len, packet->text, len * 2);

の部分を

MultiByteToWideChar(CP_ACP, 0, msg, len, reinterpret_cast< wchar_t* >(packet->text), len * 2);

と書き換えてください。

どちらも、符号なし16ビット型だと思うのでおそらくreinteroret_castでいけると思います。

keichan

Re:古いソフトの再ビルド

#8

投稿記事 by keichan » 18年前

>u16 text[0];
この表記はコピーミスでない限り、コンパイルエラーになると思います。
(要素数0個の固定長配列変数は定義できない)

u16 text[(適度な任意の数)];
と変更してください。

GPGA

Re:古いソフトの再ビルド

#9

投稿記事 by GPGA » 18年前

> この表記はコピーミスでない限り、コンパイルエラーになると思います。
>(要素数0個の固定長配列変数は定義できない)
たぶん使用していたコンパイラの拡張機能なのでしょう。
たしかgccができたようなできないような・・・。

> u16 text[(適度な任意の数)];
> と変更してください。
ここの部分についてなのですが
[color=00B0FF]#include[/color] <stdio.h>
[color=00B0FF]#include[/color] <stdlib.h>
[color=00B0FF]#include[/color] <string.h>

[color=00B0FF">typedef[/color] [color=00B0FF]struct[/color] tagData
{
    [color=00B0FF]int[/color]     size;
    [color=00B0FF]char[/color]    buf[1];
} Data;

[color=00B0FF">int[/color] main([color=00B0FF]void[/color]) {
    Data* pData;
    pData = (Data*)malloc([color=00B0FF]sizeof[/color](Data) + strlen("あいうえお") + 1);
    pData->size = strlen("あいうえお");
    strcpy(pData->buf, "あいうえお");

    printf("%s\n", pData->buf);
    free(pData);
    [color=00B0FF]return[/color] 0;
}
上記のように、構造体の一番最後に、要素数1の配列を用意しておき、構造体の領域確保時に
余分に領域を取るという手法を使用しているのではないかと思います。
Windowsでも、BITMAPINFO構造体がこの形式を取っていたはずです。

ただ、私も文献で得た情報であり、実際にそれを自分の手で打ったことがないため
確実にそうであるとはいえませんが。

GPGA

Re:古いソフトの再ビルド

#10

投稿記事 by GPGA » 18年前

>> この表記はコピーミスでない限り、コンパイルエラーになると思います。
>>(要素数0個の固定長配列変数は定義できない)
> たぶん使用していたコンパイラの拡張機能なのでしょう。
> たしかgccができたようなできないような・・・。
どちらにしてもVS2005では、エラーになりますね。
初心者さんは [0] を [1] にして試してみてください。

keichan

Re:古いソフトの再ビルド

#11

投稿記事 by keichan » 18年前

> たしかgccができたようなできないような・・・。
そうなんですか。それは知りませんでした。

しかし、もしそうであるとしてもなぜ
char* text;
とせずに
char text[0];
にしているのかが納得できません。

#もしかして配置アドレスを固定したいからかな?

GPGA

Re:古いソフトの再ビルド

#12

投稿記事 by GPGA » 18年前

私も、実際にこの手法のメリット、デメリットを知っているわけではないため
憶測に過ぎないのですが、構造体全体をmallocして開放することによる開放ミスを防ぐとか
その構造体一つで、連続したメモリを確保できるとかでしょうか?

例えば以下の構造体があったとしましょう。
[color=00B0FF]struct[/color] Data
{
    [color=00B0FF]int[/color]     num[100];
    [color=00B0FF]char[/color]*   buf;
};
この構造体のbufを別で400バイト分確保しようとしたときに、num[100]の400バイト([color=00B0FF]int[/color]=4byteとして)と
bufの400バイトが別の領域に作成されて、メモリが断片化しますね。
しかし、
[color=00B0FF]struct[/color] Data
{
    [color=00B0FF]int[/color]     num[100];
    [color=00B0FF]char[/color]    buf[1];
};
この方法で構造体を最初にmallocすれば800バイト分の領域が一度に確保されて、メモリ断片化が極力防げます。
今でこそメモリが多いため、そのようなことは気にしませんが、昔はメモリが少なかったからこのような方法を
取ったのではないでしょうか?

あくまで憶測ですけどね。
実際に知っている方がいたら教えてください。

keichan

Re:古いソフトの再ビルド

#13

投稿記事 by keichan » 18年前

なるほど。
フラグメント/リークの危険の面から見てもメリットはありそうですね。
私はバイナリファイルを保存する時に楽だなぁ。。。
くらいしか思いつきませんでした。

どちらにしてもこういう方法は今風ではない感じがします。

#私は専らC++畑で仕事をしていますのでよくわかっていませんが。

GPGA

Re:古いソフトの再ビルド

#14

投稿記事 by GPGA » 18年前

> どちらにしてもこういう方法は今風ではない感じがします。
はい、私もそう思います。

私もどちらかというとC++で記述する人間で、先ほどの例で言ってしまえば以下のように書いちゃいます。
[color=00B0FF]class[/color] Data
{
[color=00B0FF]public[/color] :
    // コンストラクタ
    Data() {
        buf = NULL;
    }
    // デストラクタ
    [color=00B0FF]virtual[/color] ~Data() {
        [color=00B0FF]delete[/color][/url] buf;
    }
    // 初期化
    [color=00B0FF]bool[/color] Init() {
        buf = [color=00B0FF">new[/color] [color=00B0FF]char[/color][400];
        [color=00B0FF]if[/color] (buf == NULL) {
            [color=00B0FF">return[/color] [color=00B0FF]false[/color];
        }
        [color=00B0FF">return[/color] [color=00B0FF]true[/color];
    }
[color=00B0FF]private[/color] :
    [color=00B0FF]int[/color]     num[400]
    [color=00B0FF]char[/color]*   buf;
};
まあ今回は、初心者さんが知り合いから頂いた古いソースということでしたので
昔はこうだったのではないかという、憶測の話を出しただけです。

keichan

Re:古いソフトの再ビルド

#15

投稿記事 by keichan » 18年前

私の場合はこんな感じですか。
Dataの扱いが単なる"データ"の塊であったらば...

#include <string>

struct Data
{
int num[400];
std::string;
};


※初心者さんへ
本題とは関係のない話で板を見づらくして申し訳ありません。

初心者

Re:古いソフトの再ビルド

#16

投稿記事 by 初心者 » 18年前

> MultiByteToWideChar(CP_ACP, 0, msg, len, reinterpret_cast< wchar_t* >(packet->text), len * 2);
>
> と書き換えてください。

こちらの方法で無事にエラーが出なくなりました。
本当にありがとうございました。
でも、別の問題が・・ 別板を立てさせてもらってます。

閉鎖

“C言語何でも質問掲示板” へ戻る