0

多くの言語をサポートする C プログラムを作成しています。プログラムは、char の代わりに WCHAR 型を使用して電子メールを送信します。問題は、メールを受信して​​読むと、一部の文字が正しく表示されないことです。e、m などの英語の文字も含まれます。これは例です。

<!-- language: lang-c -->
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(hnd, CURLOPT_READDATA, &upload_ctx);

static const WCHAR *payload_text[]={
    L"To: <me@mail.com>\n",
    L"From: <me@mail.com>(Example User)\n",
    L"Subject: Hello!\n",
    L"\n",
    L"Message sent\n",
    NULL
};

struct upload_status {
    int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp){
    struct upload_status *upload_ctx = (struct upload_status *)userp;
    const WCHAR *data;

    if ((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
        return 0;
    }

    data = payload_text[upload_ctx->lines_read];
    if (data) {
        size_t len = wcslen(data);
        memcpy(ptr, data, len);
        upload_ctx->lines_read ++;
        return len;
    }
    return 0;
}
4

1 に答える 1

0

memcpy()文字ではなく、バイトで動作します。あなたはそれを考慮していませんsizeof(wchar_t) > 1。一部のシステムでは 2 バイトで、他のシステムでは 4 バイトです。この不一致はwchar_t、移植可能なコードを作成する場合に不適切な選択になります。代わりに、icu や iconv などの Unicode ライブラリを使用する必要があります)。

sizeof(wchar_t)を呼び出すときは、考慮する必要がありますmemcpy()。また、宛先バッファが、コピーしようとしているテキスト バイトのサイズよりも小さい可能性があることも考慮する必要があります。を追跡するlines_readだけでは十分ではありません。コピーした現在の行のバイト数も追跡する必要があるため、テキストの現在の行が複数の宛先バッファーにまたがっている場合に対処できます。

代わりに、次のようなことを試してください。

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
    struct upload_status *upload_ctx = (struct upload_status *) userp;
    unsigned char *buf = (unsignd char *) ptr;
    size_t available = (size * nmemb);
    size_t total = 0;

    while (available > 0)
    {
        wchar_t *data = payload_text[upload_ctx->lines_read];
        if (!data) break;

        unsigned char *rawdata = (unsigned char *) data;

        size_t remaining = (wcslen(data) * sizeof(wchar_t)) - upload_ctx->line_bytes_read;
        while ((remaining > 0) && (available > 0))
        {
            size_t bytes_to_copy = min(remaining, available);
            memcpy(buf, rawdata, bytes_to_copy);

            buf += bytes_to_copy;
            available -= bytes_to_copy;
            total = bytes_to_copy;

            rawdata += bytes_to_copy;
            remaining -= bytes_to_copy;

            upload_ctx->line_bytes_read += bytes_to_copy;
        }

        if (remaining < 1)
        {
            upload_ctx->lines_read ++;
            upload_ctx->line_bytes_read = 0;
        }
    }

    return total;
}
于 2012-08-11T02:14:11.727 に答える