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

时间:2012-04-08 21:11:37

标签: c# dll delegates interop dllimport

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

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

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

并导出一个字段,如:

 EXTERN t_libpd_printhook libpd_printhook;

现在我使用Interop Assistant生成绑定代码,这只给了我一个委托定义:

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

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

2 个答案:

答案 0 :(得分:4)

您可以使用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);

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

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

答案 1 :(得分:3)

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