0

有人可以指出我这段代码有什么问题吗?我在混合 C++ 和 MC++ 方面有过非常艰难的经历。我已经阅读了很多关于这个主题的博客和教程(传递代表),但现在看起来我的代码还可以(它在调试模式下编译和运行良好,并且逐步运行)它崩溃了。

主要问题是它需要一个作为成员函数的 Delegate (需要访问其他类成员)。

我记得 waveInProc 文档中有一条注释说在回调中你不能调用任何系统函数。这应该是导致应用程序崩溃的原因吗,因为它尝试使用其他成员并且托管环境发生在这里调用其他系统方法?

ref class CWaveIn
{
public:
 void CWaveIn::Open(int currentInputDeviceId)
private:
 void AllocateBuffer(void);
 void WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
 delegate void CallBack(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
 CallBack^ myDelegate;
protected:
 WAVEFORMATEX* waveFormat;
 int bufferDuration; // in seconds
 BYTE* waveInBuffer;
 int bufferSize;
};

void CWaveIn::AllocateBuffer(void)
{
 free(waveInBuffer);
 bufferSize = waveFormat->nAvgBytesPerSec * bufferDuration;
 waveInBuffer = new BYTE[bufferSize];
 Debug::WriteLine("BufferSize: " + bufferSize);
}

void CWaveIn::WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) 
{
 switch(uMsg) {
  case WIM_CLOSE:
   Debug::WriteLine("WIM_CLOSE");
   break;
  case WIM_DATA:
   for(int i=0;i<bufferSize; i++) {
    Debug::Write(waveInBuffer[i] + " ");
   }
   Debug::WriteLine("WIM_DATA");
   break;
  case WIM_OPEN:
   Debug::WriteLine("WIM_OPEN");
   break;
 }
}

void CWaveIn::Open(int currentInputDeviceId) 
{
 MMRESULT result = ::waveInOpen(0, currentInputDeviceId, waveFormat, 0, 0, WAVE_FORMAT_QUERY);
 Debug::WriteLine(L"CWaveIn::Open() WAVE_FORMAT_QUERY: device " + currentInputDeviceId.ToString());
 DebugError(result);
 if(result == MMSYSERR_NOERROR)
 {
  myDelegate = gcnew CallBack(this, &CWaveIn::WaveInProc);
  pin_ptr<CallBack^> ptrMyDelegate= &myDelegate;
  IntPtr delegatePointer = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(myDelegate);

  HWAVEIN hWaveIn;
  MMRESULT result = ::waveInOpen(&hWaveIn, currentInputDeviceId, waveFormat, (DWORD_PTR)delegatePointer.ToPointer(), 0, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT);
  Debug::WriteLine(L"CWaveIn::Open() : device " + currentInputDeviceId.ToString());
  DebugError(result);

  AllocateBuffer();

  WAVEHDR WaveInHdr;
  WaveInHdr.lpData = (LPSTR)waveInBuffer;
  WaveInHdr.dwBufferLength = bufferSize;
  WaveInHdr.dwBytesRecorded=0;
  WaveInHdr.dwUser = 0L;
  WaveInHdr.dwFlags = 0L;
  WaveInHdr.dwLoops = 0L;
  ::waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
  result = ::waveInAddBuffer(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));

  result = ::waveInStart(hWaveIn);
  Debug::WriteLine(L"CWaveIn::Start() : device " + currentInputDeviceId.ToString());
  DebugError(result);
 }
}
4

2 回答 2

1

您需要使用 GCHandle 而不是 pin_ptr。请参阅http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.80).aspx

于 2012-01-06T10:37:20.957 回答
0

你在托管堆上声明 pin_ptr 然后你将它传递给一个非托管函数,所有对这个指针的托管引用都在里面 ,所以我猜 GC 认为没有理由在退出CWaveIn::Open(int currentInputDeviceId) 后保留这个对象。CWaveIn::Open

尝试在类范围而不是函数范围内创建它

于 2010-01-03T09:37:51.903 回答