从 C# 设置非托管 C dll 的公共字段

本文关键字:dll 字段 设置 | 更新日期: 2023-09-27 18:30:23

我正在为非托管的C dll编写C#绑定。

dll 提供了 5 个钩子来返回多个数据:

typedef void (*t_libpd_printhook)(const char *recv);

并导出如下字段:

 EXTERN t_libpd_printhook libpd_printhook;

现在我正在使用互操作助手来生成绑定代码,它只给了我一个委托定义:

public delegate void t_libpd_printhook([In] [MarshalAs(UnmanagedType.LPStr)] string recv);

那么我可以使用一些神奇的互操作函数调用来设置 DLL 中的t_libpd_printhook字段吗?

从 C# 设置非托管 C dll 的公共字段

可以使用

LoadLibraryGetProcAddress来获取指向导出的libpd_printhook变量的指针。然后,您可以使用Marshal.WriteIntPtrMarshal.GetFunctionPointerForDelegate分配给代理。

[DllImport("kernel32", SetLastError=true, CharSet=CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, 
    SetLastError=true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);
.....
IntPtr lib = LoadLibrary(@"mydll.dll");
IntPtr plibpd_printhook = GetProcAddress(lib, "libpd_printhook");
Marshal.WriteIntPtr(plibpd_printhook, 
    Marshal.GetFunctionPointerForDelegate(mydelegate));
FreeLibrary(lib);

为了简洁的示例,您将需要添加我删除的错误检查。

现在,如果您控制非托管库,我仍然建议添加一个函数来封装对此函数指针的写入。这对我来说是一个更好的界面。

> PInvoke 不支持导出的变量。您需要创建一个非托管函数,该函数获取委托并将其复制到字段中。