You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++使用SAPI实现TTS时字符串参数调用Speak函数失败求助

解决SAPI文本转语音函数ISpVoice::Speak的参数类型不兼容问题

核心问题是**ISpVoice::Speak的第一个参数要求宽字符指针(LPCWSTR)**,而你传入的std::string是窄字符类型,类型不匹配导致代码无法编译或运行。你之前尝试的L + text是错误语法(L只能用于字符串字面量前缀),直接传递std::string对象同样不满足参数要求。

方案1:改用宽字符串参数(推荐)

直接将函数参数改为std::wstring,调用时使用宽字符串字面量(前缀L):

#include <iostream>
#include <sapi.h>
#include <string>

using namespace std;

void bot(wstring text)
{
    ISpVoice* pVoice = NULL;
    if (FAILED(::CoInitialize(NULL)))
    {
        exit(1);
    }
    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
    if (SUCCEEDED(hr))
    {
        // 调用c_str()获取LPCWSTR类型的宽字符指针
        hr = pVoice->Speak(text.c_str(), 0, NULL);
        pVoice->Release();
        pVoice = NULL;
    }
    ::CoUninitialize();
}

int main()
{
    bot(L"Hello");
    bot(L"Hi, my name is blah blah");
    return 0;
}

方案2:保留窄字符串参数,添加类型转换

如果需要继续使用std::string作为参数,需要将窄字符串转换为宽字符串,可借助Windows API实现转换:

#include <iostream>
#include <sapi.h>
#include <string>
#include <windows.h>

using namespace std;

// 窄字符串转宽字符串(UTF-8编码)
wstring string_to_wstring(const string& str)
{
    int wide_size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), NULL, 0);
    wstring wide_str(wide_size, 0);
    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wide_str[0], wide_size);
    return wide_str;
}

void bot(string text)
{
    ISpVoice* pVoice = NULL;
    if (FAILED(::CoInitialize(NULL)))
    {
        exit(1);
    }
    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
    if (SUCCEEDED(hr))
    {
        wstring wide_text = string_to_wstring(text);
        hr = pVoice->Speak(wide_text.c_str(), 0, NULL);
        pVoice->Release();
        pVoice = NULL;
    }
    ::CoUninitialize();
}

int main()
{
    bot("Hello");
    bot("Hi, my name is blah blah");
    return 0;
}

额外注意事项

  • 编译时必须链接SAPI库:在Visual Studio中,需在项目属性的链接器 -> 输入 -> 附加依赖项中添加sapi.lib,否则会出现未定义符号的链接错误。
  • 更规范的做法是将CoInitialize放在程序入口(main开头)调用一次,CoUninitialize放在程序退出前调用一次,避免每次调用bot函数重复初始化/释放COM环境。

内容的提问来源于stack exchange,提问作者MaxMouse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:01:56