我使用 PortAudioSharp 作为 PortAudio (PA) 的 C# 包装器。但是这个问题更笼统,所以为了清楚起见,我将略去代码。
PA 有一个回调,当它需要新数据时会调用它。所以打开一个流将使用这个函数:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate PaStreamCallbackResult PaStreamCallbackDelegate(IntPtr input, IntPtr userData);
[DllImport("PortAudio.dll")]
public static PaError Pa_OpenStream(out IntPtr stream, PaStreamCallbackDelegate streamCallback, IntPtr userData);
我现在有一个类,它运行一个解码器,填充该类中的缓冲区。我希望 PA 从该类中回调一个函数以获取新数据。代码是这样的:
class CFoo{
private PaStreamCallbackDelegate _PaStreamCallback;
void Open(){
_PaStreamCallback = _ProcessNewData;
IntPtr myStream;
Pa_OpenStream(out myStream, _PaStreamCallback, IntPtr.Zero);
}
private PaStreamCallbackResult _ProcessNewData(IntPtr input, IntPtr userData){
var buf = new byte[SIZE];
// Fill buf ... and then:
Marshal.Copy(buf, 0, output, buf.Length);
return PaStreamCallbackResult.paContinue;
}
}
到目前为止,这似乎有效。问题:有时当有超过 1 个流(1 个暂停,1 个正在运行)时,会调用错误流的回调。我认为,代表可能是问题所在。
所以问题:
1)以上是否正确?我可以将成员函数作为委托传递给 C++ 吗?
2)这是如何工作的?如果它是 C++ 而不是 C#,则必须创建一个 C 绕行函数,它将 userData 指针转换为一个类,然后调用类回调(例如 ((CFoo*) userData)->_ProcessNewData) 运行时是否使用一些“魔术”所以调用来自正确实例的函数?