调用C#中包含回调的C++函数
本文关键字:C++ 函数 回调 包含 调用 | 更新日期: 2023-09-27 18:27:38
嘿,我正试图在c#中调用这个c++函数:
BOOL __stdcall CodecStart(int hRadio,void __stdcall (*CallbackFunc)(void *),void *CallbackTarget);
这是来自此处的WinRadio apihttp://www.winradio.com/home/g305_sdk.htm.
我确实发现其他人询问过在网上调用这个特定的函数,他们得到了:
public delegate void CallbackFunc( IntPtr p);
[DllImport("WRG305API.dll")]
public static extern bool CodecStart(int hRadio, CallbackFunc func, IntPtr CallbackTarget);
但我不知道如何进一步实现这一点。
关于如何称呼这件事,有什么想法或指导吗?
非常感谢
这里有一个简单的实现,它将把所有这些放在一起。
class WinRadioWrapper
{
public delegate void CallbackFunc( IntPtr pData );
[DllImport( "WRG305API.dll" )]
public static extern bool CodecStart( int hRadio, CallbackFunc func, IntPtr CallbackTarget );
public bool CodecStartTest(int hRadio)
{
bool bStarted = CodecStart( hRadio, MyCallbackFunc, IntPtr.Zero );
return bStarted;
}
// Note: this method will be called from a different thread!
static void MyCallbackFunc( IntPtr pData )
{
// Sophisticated work goes here...
}
}
注意,因为
MyCallbackFunc
将在不同的线程上执行,所以我选择将其设为static
。这样,您就不会想访问WinRadioWrapper
数据成员。为了简单起见,我向回调传递了一个
IntPtr.Zero
参数,但这可以指向您想在回调中使用的任何数据
[请忽略此段落]如果您想将数据传递给回调,请查看Marshal.StructureToPtr
,但也要固定您正在传递的数据,以确保它不会被垃圾收集(有关更多详细信息,请参阅GCHandle
)
编辑:
有了svick有趣的话(谢谢!),我意识到我把复制的东西和固定的东西混合在一起了。
所以,为了解决问题:
- 如果要复制现有的数据结构,然后将其传递给回调函数,则应使用
Marshal.StructureToPtr
- 另一方面,如果您想使用和现有的数据结构(例如,用于修改其内容),则应使用
GCHandle
,以便将固定在内存中,并防止其被垃圾收集
但是,这将增加GCHandle
的一些维护开销
回调函数是由执行某些函数的dll(在本例中是导入的)调用的代码。您还需要学习如何在c#中使用委托。你可以实现这样的代码:
public void MyCallback(IntPtr p)
{
//do something
}
然后你的dll调用会是这样的:
[DllImport("WRG305API.dll")]
public static extern bool CodecStart(int hRadio, func, IntPtr CallbackTarget);
如果您需要更多指导,请发布您想要转换的代码的C++版本,我们可以帮助您使用C#版本。
您所需要做的就是创建一个与您声明的委托的签名匹配的c#函数。创建一个委托,保留对此委托的引用,这样它就不会被垃圾收集,并将该委托作为回调调用dll导入。
所以你会有这样的东西:
public void MyCallback(IntPtr P)
{
//do something
}
// somewhere else in your code
var cb = new CallbackFunc(MyCallback);
CodecStart(..., cb, ...);