DLL 以 C++ 风格导出,并添加了函数修饰符。动态库导出的接口名称如下:
实际函数名称:
RegPOC_CB
动态库中接口名称:
?RegPOC_CB@@YAHPAUPOC_CB_t@@@Z
RegPOC_CB
函数定义如下,接收存储回调函数的POC_CB_t
结构体指针。
define EXPORT __declspec(dllexport)
typedef void (*CmdOutCallBack)(char* pAtStrCmd);
typedef void (*RADataCallBack)(const char *src , int len,int type) ;
typedef void (*RVDataCallBack)(const char *src , int len,int type, int width,int high,int rota);
typedef struct
{
CmdOutCallBack cmdOutCB;
RADataCallBack rADataCB;
RVDataCallBack rVDataCB;
CmdOutCallBack LOCB;
}POC_CB_t;
extern int EXPORT RegPOC_CB(POC_CB_t *pCbFunc);
我使用以下代码在C#中注册了回调函数,但是调试时回调函数实现中的所有打印都没有效果。单步调试时,显示调用
RegPOC_CB
函数成功,没有报错。你知道为什么吗?
public class Sender(int id)
{
public int Id { get; set; } = id;
[DllImport("say.dll", EntryPoint = "?RegPOC_CB@@YAHPAUPOC_CB_t@@@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int RegPOC_CB(ref POC_CB_t pCbFunc);
// Using IntPtr has no effect either
// public static extern int RegPOC_CB(IntPtr pCbFunc);
// Define a C# delegate that matches the C++ callback function
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CmdOutCallBack(IntPtr pAtStrCmd);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void RADataCallBack(IntPtr src, int len, int type);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void RVDataCallBack(IntPtr src, int len, int type, int width, int height, int rota);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LOCallBack(IntPtr message);
// POC_CB_t struct
[StructLayout(LayoutKind.Sequential)]
public struct POC_CB_t
{
public CmdOutCallBack cmdOutCB;
public RADataCallBack rADataCB;
public RVDataCallBack rVDataCB;
public LOCallBack LOCB;
}
// Callback function implementation
public void cmdOut(IntPtr pAtStrCmd)
{
System.Diagnostics.Debug.WriteLine("call cmdOut");
var at = Marshal.PtrToStringAnsi(pAtStrCmd);
if (string.IsNullOrWhiteSpace(at)) { return; }
System.Diagnostics.Debug.WriteLine($"[{id}] cmdOut Callback: {at}");
}
public void rAData(IntPtr src, int len, int type)
{
System.Diagnostics.Debug.WriteLine("call rADataCB");
byte[] buffer = new byte[len];
Marshal.Copy(src, buffer, 0, len);
var data = buffer.ToString();
System.Diagnostics.Debug.WriteLine($"[{id}] Data: {data}, Length: {len}, Type: {type}");
}
public void rVData(IntPtr src, int len, int type, int width, int height, int rota)
{
System.Diagnostics.Debug.WriteLine("call RecvVideoData");
byte[] buffer = new byte[len];
Marshal.Copy(src, buffer, 0, len);
var data = buffer.ToString();
System.Diagnostics.Debug.WriteLine($"[{id}] Data: {data}, Length: {len}, Type: {type}, Width: {width}, Height: {height}, Rotation: {rota}");
}
public void LO(IntPtr message)
{
System.Diagnostics.Debug.WriteLine("call LogOut");
var LogStr = Marshal.PtrToStringAnsi(message);
if (string.IsNullOrWhiteSpace(LogStr)) { return; }
System.Diagnostics.Debug.WriteLine($"[{id}] Log: {LogStr}");
}
// call RegPOC_CB
public void RegisterCallbacks()
{
callbacks = new POC_CB_t
{
cmdOutCB = cmdOut,
rADataCB = rAData,
rVDataCB = rVData,
LOCB = LO
};
RegPOC_CB(ref callbacks);
// Using IntPtr has no effect either
//IntPtr pCallbacks = Marshal.AllocHGlobal(Marshal.SizeOf(callbacks));
//Marshal.StructureToPtr(callbacks, pCallbacks, false);
//RegPOC_CB(pCallbacks);
InitPoc(0);
}
}
我尝试过使用
ref
和IntPtr
将结构体指针传递到DLL中,但结果是一样的。
您似乎正在尝试将回调函数从 C# 应用程序注册到 C++ 动态链接库 (DLL)。 C++ DLL 导出一个名为“RegPOC_CB”的函数,该函数采用指向包含回调函数的结构的指针。 C# 代码定义回调函数并尝试使用“RegPOC_CB”函数注册它们。 您提供的 C++ 代码看起来大部分是正确的,但有一些潜在的问题可能会导致您遇到的问题。以下是一些有助于排除故障并可能解决问题的建议:
通过仔细检查这些方面并可能进行调整,您也许能够解决问题。如果问题仍然存在,请考虑使用 Dependency Walker 等工具或调试器来检查 C++ DLL 中的导出函数及其签名。此外,捕获 RegPOC_CB 函数返回的任何错误代码或消息可以为问题提供有价值的见解。