0

我正在制作一个支持多种语言的 C 程序。该程序使用 WCHAR 类型而不是 char 类型发送电子邮件。问题是,当我收到邮件并阅读时,有些字符显示不正确,甚至有些英文字符,如 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一个糟糕的选择。您应该改用 Unicode 库,例如 icu 或 iconv)。

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 回答