做一个TTS发音的DLL,代码如下:#include "stdafx.h"
#include <sapi.h>#pragma comment(lib,"ole32.lib") //CoInitialize CoCreateInstance需要调用ole32.dll
#pragma comment(lib,"sapi.lib") //sapi.lib在SDK的lib目录,必需正确配置
void WINAPI  speak(LPCWSTR sts);
void init();
void rel();
ISpVoice * pVoice = NULL;
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
    switch (ul_reason_for_call)
   {
case DLL_PROCESS_ATTACH:
     init();    //DLL调用初始化voice
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
     rel();   //程序退出时释放voice
     break;
    }
    return TRUE;
}
void WINAPI speak(LPCWSTR sts)  //TTS发音
{
 pVoice->Speak(sts, 1, NULL);
}void init()   //voice初始化
{
   ::CoInitialize(NULL);  //COM初始化:    //获取ISpVoice接口:
    CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
}void rel()  //释放PVOICE
{
    pVoice->Release();
    pVoice = NULL;
    ::CoUninitialize();
}
想在调用DLL的程序退出时,将voice释放,所以在dllmain中有:
case DLL_PROCESS_DETACH:
     rel();   //程序退出时释放voice
     break;
但是,一加上rel();就出错,只好将这个代码去掉,结果就运行正常了。不知这是怎么回事。

解决方案 »

  1.   

    遵守几个原则:
      1、启动组件得到一个接口指针(Interface)后,不要调用AddRef()。因为系统知道你得到了一个指针,所以它已经帮你调用了AddRef()函数;
      2、通过QueryInterface()得到另一个接口指针后,不要调用AddRef()。因为......和上面的道理一样;
      3、当你把接口指针赋值给(保存到)另一个变量中的时候,请调用AddRef();
      4、当不需要再使用接口指针的时候,务必执行Release()释放;
      5、当使用智能指针的时候,可以省略指针的维护工作;
      

  2.   

    谢谢啊。我正在学VC,所以这些指针还搞不清楚。
    不过,现在做的DLL也没发现内存泄露问题,先这么用着了。另,将rel() 中的 pVoice->Release();和  pVoice = NULL;这两行代码去掉,就可以正常使用了。
    void rel()  //释放PVOICE
    {
       // pVoice->Release();
       // pVoice = NULL;
        ::CoUninitialize();
    }