gpt4 book ai didi

c# - 将 C 函数指针设置为 C# 函数

转载 作者:太空狗 更新时间:2023-10-29 15:05:54 28 4
gpt4 key购买 nike

我需要在 C 库中设置一个回调函数等同于一个 C# 函数,并且在没有 dlopen 或 kernel32 的情况下无法找到一种方法,这似乎是 windows/unix 特定的。有谁知道这样做的方法吗?

问题:C 共享库暴露了函数指针,其值应该通过覆盖它们来设置。例如。

//C Code
extern void (*ptr_R_ShowMessage) (const char *)

当前的 C# 代码为匹配此签名的函数创建一个委托(delegate),使用 marshal 类获取指向该委托(delegate)的指针,然后用此值覆盖 C 指针。

//call to libdl or kernel32.dll 
IntPtr showPointer = GetFunctionAddress(hndl,"ptr_R_ShowMessage");
IntPtr newShowPointer = Marshal.GetFunctionPointerForDelegate(matchingDelegate);
Marshal.WriteIntPtr(showPointer, newShowPointer);

对 libdl 和 kernel32.dll 的要求会导致各种问题......理想情况下应该避免。

有谁知道如何在不修改 C 代码或使用 GetFunctionAddress 动态加载的情况下使 C 库指针指向 C# 代码?我认为这可能是不可能的,但它似乎是可能的。

最佳答案

我不能 100% 确定这是否是您要找的。

在我们的例子中,我们有一个第三方 C SDK,它为回调消息提供了几个 Hook 。回调调用在 C 代码中启动并期望调用 C 函数,但我们可以使用以下步骤将其 Hook 到 C# 方法。 (此代码有点旧,可能有更简洁和现代的方法可以在较新的 C# 迭代中实现相同的功能)。

首先,我们在 C# 类中声明一个回调委托(delegate),它与 SDK 期望的 C 函数指针的签名兼容。

例如,如果 C 代码期望回调具有以下签名的函数:

void DecCallBack(int nPort, void* pBuf, int nSize, FRAME_INFO *pInfo, int nReserved1, int reserved 2);

这是匹配的 C# 委托(delegate)定义。请注意,“魔法”的发生要归功于 UnmanagedFunctionPointer属性:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate void DecCallBack(int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO frameInfo, int nReserved1, int nReserved2);

一旦有了这个,我们就声明一个 DecCallBack 类型的类成员它将在我们的类中持有一个委托(delegate)实例。

static DecCallBack _decodeCallBack = null;

接下来我们编写一个与委托(delegate)签名兼容的处理程序方法。在这种情况下,我们将其命名为 HandleDecData()

private static void HandleDecData(int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO frameInfo, int nReserved1, int nReserved2) {

// Here we handle the callback, this code is being called from an external C library

}

接下来,在 C# 类的某处,我们需要初始化委托(delegate)成员并 Hook 我们的回调处理程序(在本例中是静态方法 HandleDecData()

_decodeCallBack += new DecCallBack(HandleDecData);

最后,我们将委托(delegate)成员作为指向 C 的函数指针传递。在我们的例子中,第三方 SDK 有一个 C PlayM4_SetDecCallBack()调用回调时期望调用函数指针的函数 - 我们可以安全地传递我们类的委托(delegate)成员。

 if( !PlayM4_SetDecCallBack(channel, _decodeCallBack) ) 
throw new InvalidOperationException("Error setting DecCallBack");

希望对您有所帮助。

关于c# - 将 C 函数指针设置为 C# 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19528493/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com