【问题标题】:Set public field of unmanaged C dll from C#从 C# 设置非托管 C dll 的公共字段
【发布时间】:2012-04-08 21:11:37
【问题描述】:

我正在为非托管 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);

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

【问题讨论】:

  • 啊,不知道那个,但是我怎么给它分配一个代表呢?
  • 是的,我现在接受了你的回答,因为它是我问题的正确答案。但由于我使用的 dll 是开源的,我可能会按照 usr 的建议添加 setter 方法。我发现这很有帮助:stackoverflow.com/questions/2167895/…
  • 有趣的问题,我同意如果您正在编译本机代码,setter 是正确的解决方案。

标签: c# dll delegates interop dllimport


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢,很好的例子!我将评估两种方式。因为我有 dll 的来源,所以我可以编写 setter 方法,正如你所建议的那样,工作量更少,界面更简洁。
【解决方案2】:

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

【讨论】:

  • 好的,所以我必须在 C 中添加 set 方法...谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
  • 2010-10-14
相关资源
最近更新 更多